mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 01:34:18 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
This commit is contained in:
		@@ -154,6 +154,7 @@ dist_tmux_SOURCES = \
 | 
			
		||||
	options-table.c \
 | 
			
		||||
	options.c \
 | 
			
		||||
	paste.c \
 | 
			
		||||
	popup.c \
 | 
			
		||||
	proc.c \
 | 
			
		||||
	regsub.c \
 | 
			
		||||
	resize.c \
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,8 @@
 | 
			
		||||
 | 
			
		||||
static enum cmd_retval	cmd_display_menu_exec(struct cmd *,
 | 
			
		||||
			    struct cmdq_item *);
 | 
			
		||||
static enum cmd_retval	cmd_display_popup_exec(struct cmd *,
 | 
			
		||||
			    struct cmdq_item *);
 | 
			
		||||
 | 
			
		||||
const struct cmd_entry cmd_display_menu_entry = {
 | 
			
		||||
	.name = "display-menu",
 | 
			
		||||
@@ -44,6 +46,21 @@ const struct cmd_entry cmd_display_menu_entry = {
 | 
			
		||||
	.exec = cmd_display_menu_exec
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const struct cmd_entry cmd_display_popup_entry = {
 | 
			
		||||
	.name = "display-popup",
 | 
			
		||||
	.alias = "popup",
 | 
			
		||||
 | 
			
		||||
	.args = { "CEKc:d:h:R:t:w:x:y:", 0, -1 },
 | 
			
		||||
	.usage = "[-CEK] [-c target-client] [-d start-directory] [-h height] "
 | 
			
		||||
	         "[-R shell-command] " CMD_TARGET_PANE_USAGE " [-w width] "
 | 
			
		||||
	         "[-x position] [-y position] [command line ...]",
 | 
			
		||||
 | 
			
		||||
	.target = { 't', CMD_FIND_PANE, 0 },
 | 
			
		||||
 | 
			
		||||
	.flags = CMD_AFTERHOOK,
 | 
			
		||||
	.exec = cmd_display_popup_exec
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
cmd_display_menu_get_position(struct client *c, struct cmdq_item *item,
 | 
			
		||||
    struct args *args, u_int *px, u_int *py, u_int w, u_int h)
 | 
			
		||||
@@ -190,3 +207,79 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
		return (CMD_RETURN_NORMAL);
 | 
			
		||||
	return (CMD_RETURN_WAIT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static enum cmd_retval
 | 
			
		||||
cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
{
 | 
			
		||||
	struct args		*args = self->args;
 | 
			
		||||
	struct client		*c;
 | 
			
		||||
	struct cmd_find_state	*fs = &item->target;
 | 
			
		||||
	const char		*value, *cmd = NULL, **lines = NULL;
 | 
			
		||||
	const char		*shellcmd = NULL;
 | 
			
		||||
	char			*cwd, *cause;
 | 
			
		||||
	int			 flags = 0;
 | 
			
		||||
	u_int			 px, py, w, h, nlines = 0;
 | 
			
		||||
 | 
			
		||||
	if ((c = cmd_find_client(item, args_get(args, 'c'), 0)) == NULL)
 | 
			
		||||
		return (CMD_RETURN_ERROR);
 | 
			
		||||
	if (args_has(args, 'C')) {
 | 
			
		||||
		server_client_clear_overlay(c);
 | 
			
		||||
		return (CMD_RETURN_NORMAL);
 | 
			
		||||
	}
 | 
			
		||||
	if (c->overlay_draw != NULL)
 | 
			
		||||
		return (CMD_RETURN_NORMAL);
 | 
			
		||||
 | 
			
		||||
	if (args->argc >= 1)
 | 
			
		||||
		cmd = args->argv[0];
 | 
			
		||||
	if (args->argc >= 2) {
 | 
			
		||||
		lines = (const char **)args->argv + 1;
 | 
			
		||||
		nlines = args->argc - 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (nlines != 0)
 | 
			
		||||
		h = nlines + 2;
 | 
			
		||||
	else
 | 
			
		||||
		h = c->tty.sy / 2;
 | 
			
		||||
	if (args_has(args, 'h')) {
 | 
			
		||||
		h = args_percentage(args, 'h', 1, c->tty.sy, c->tty.sy, &cause);
 | 
			
		||||
		if (cause != NULL) {
 | 
			
		||||
			cmdq_error(item, "height %s", cause);
 | 
			
		||||
			free(cause);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (nlines != 0)
 | 
			
		||||
		w = popup_width(item, nlines, lines, c, fs) + 2;
 | 
			
		||||
	else
 | 
			
		||||
		w = c->tty.sx / 2;
 | 
			
		||||
	if (args_has(args, 'w')) {
 | 
			
		||||
		w = args_percentage(args, 'w', 1, c->tty.sx, c->tty.sx, &cause);
 | 
			
		||||
		if (cause != NULL) {
 | 
			
		||||
			cmdq_error(item, "width %s", cause);
 | 
			
		||||
			free(cause);
 | 
			
		||||
			return (CMD_RETURN_ERROR);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmd_display_menu_get_position(c, item, args, &px, &py, w, h);
 | 
			
		||||
 | 
			
		||||
	value = args_get(args, 'd');
 | 
			
		||||
	if (value != NULL)
 | 
			
		||||
		cwd = format_single(NULL, value, c, fs->s, fs->wl, fs->wp);
 | 
			
		||||
	else
 | 
			
		||||
		cwd = xstrdup(server_client_get_cwd(c, fs->s));
 | 
			
		||||
 | 
			
		||||
	value = args_get(args, 'R');
 | 
			
		||||
	if (value != NULL)
 | 
			
		||||
		shellcmd = format_single(NULL, value, c, fs->s, fs->wl, fs->wp);
 | 
			
		||||
 | 
			
		||||
	if (args_has(args, 'K'))
 | 
			
		||||
		flags |= POPUP_WRITEKEYS;
 | 
			
		||||
	if (args_has(args, 'E'))
 | 
			
		||||
		flags |= POPUP_CLOSEEXIT;
 | 
			
		||||
	if (popup_display(flags, item, px, py, w, h, nlines, lines, shellcmd,
 | 
			
		||||
	    cmd, cwd, c, fs) != 0)
 | 
			
		||||
		return (CMD_RETURN_NORMAL);
 | 
			
		||||
	return (CMD_RETURN_WAIT);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -273,7 +273,7 @@ cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	else
 | 
			
		||||
		cdata->item = item;
 | 
			
		||||
 | 
			
		||||
	server_client_set_overlay(c, delay, cmd_display_panes_draw,
 | 
			
		||||
	server_client_set_overlay(c, delay, NULL, NULL, cmd_display_panes_draw,
 | 
			
		||||
	    cmd_display_panes_key, cmd_display_panes_free, cdata);
 | 
			
		||||
 | 
			
		||||
	if (args_has(args, 'b'))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								cmd.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								cmd.c
									
									
									
									
									
								
							@@ -43,6 +43,7 @@ extern const struct cmd_entry cmd_delete_buffer_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_detach_client_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_display_menu_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_display_message_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_display_popup_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_display_panes_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_down_pane_entry;
 | 
			
		||||
extern const struct cmd_entry cmd_find_window_entry;
 | 
			
		||||
@@ -132,6 +133,7 @@ const struct cmd_entry *cmd_table[] = {
 | 
			
		||||
	&cmd_detach_client_entry,
 | 
			
		||||
	&cmd_display_menu_entry,
 | 
			
		||||
	&cmd_display_message_entry,
 | 
			
		||||
	&cmd_display_popup_entry,
 | 
			
		||||
	&cmd_display_panes_entry,
 | 
			
		||||
	&cmd_find_window_entry,
 | 
			
		||||
	&cmd_has_session_entry,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								job.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								job.c
									
									
									
									
									
								
							@@ -17,6 +17,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
@@ -203,6 +204,24 @@ job_free(struct job *job)
 | 
			
		||||
	free(job);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Resize job. */
 | 
			
		||||
void
 | 
			
		||||
job_resize(struct job *job, u_int sx, u_int sy)
 | 
			
		||||
{
 | 
			
		||||
	struct winsize	 ws;
 | 
			
		||||
 | 
			
		||||
	if (job->fd == -1 || (~job->flags & JOB_PTY))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	log_debug("resize job %p: %ux%u", job, sx, sy);
 | 
			
		||||
 | 
			
		||||
	memset(&ws, 0, sizeof ws);
 | 
			
		||||
	ws.ws_col = sx;
 | 
			
		||||
	ws.ws_row = sy;
 | 
			
		||||
	if (ioctl(job->fd, TIOCSWINSZ, &ws) == -1)
 | 
			
		||||
		fatal("ioctl failed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Job buffer read callback. */
 | 
			
		||||
static void
 | 
			
		||||
job_read_callback(__unused struct bufferevent *bufev, void *data)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								menu.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								menu.c
									
									
									
									
									
								
							@@ -130,6 +130,16 @@ menu_free(struct menu *menu)
 | 
			
		||||
	free(menu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
menu_mode_cb(struct client *c, __unused u_int *cx, __unused u_int *cy)
 | 
			
		||||
{
 | 
			
		||||
	struct menu_data	*md = c->overlay_data;
 | 
			
		||||
 | 
			
		||||
	if (~md->flags & MENU_NOMOUSE)
 | 
			
		||||
		return (MODE_MOUSE_ALL);
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
menu_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0)
 | 
			
		||||
{
 | 
			
		||||
@@ -147,9 +157,6 @@ menu_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0)
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < screen_size_y(&md->s); i++)
 | 
			
		||||
		tty_draw_line(tty, NULL, s, 0, i, menu->width + 4, px, py + i);
 | 
			
		||||
 | 
			
		||||
	if (~md->flags & MENU_NOMOUSE)
 | 
			
		||||
		tty_update_mode(tty, MODE_MOUSE_ALL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -317,7 +324,7 @@ menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px,
 | 
			
		||||
	md->cb = cb;
 | 
			
		||||
	md->data = data;
 | 
			
		||||
 | 
			
		||||
	server_client_set_overlay(c, 0, menu_draw_cb, menu_key_cb, menu_free_cb,
 | 
			
		||||
	    md);
 | 
			
		||||
	server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb,
 | 
			
		||||
	    menu_key_cb, menu_free_cb, md);
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										447
									
								
								popup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										447
									
								
								popup.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,447 @@
 | 
			
		||||
/* $OpenBSD$ */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@gmail.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
 * purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 * copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "tmux.h"
 | 
			
		||||
 | 
			
		||||
struct popup_data {
 | 
			
		||||
	struct client		 *c;
 | 
			
		||||
	struct cmdq_item	 *item;
 | 
			
		||||
	int			  flags;
 | 
			
		||||
 | 
			
		||||
	char			**lines;
 | 
			
		||||
	u_int			  nlines;
 | 
			
		||||
 | 
			
		||||
	char			 *cmd;
 | 
			
		||||
	struct cmd_find_state	  fs;
 | 
			
		||||
	struct screen		  s;
 | 
			
		||||
 | 
			
		||||
	struct job		 *job;
 | 
			
		||||
	struct input_ctx	 *ictx;
 | 
			
		||||
	int			  status;
 | 
			
		||||
 | 
			
		||||
	u_int			  px;
 | 
			
		||||
	u_int			  py;
 | 
			
		||||
	u_int			  sx;
 | 
			
		||||
	u_int			  sy;
 | 
			
		||||
 | 
			
		||||
	enum { OFF, MOVE, SIZE }  dragging;
 | 
			
		||||
	u_int			  dx;
 | 
			
		||||
	u_int			  dy;
 | 
			
		||||
 | 
			
		||||
	u_int			  lx;
 | 
			
		||||
	u_int			  ly;
 | 
			
		||||
	u_int			  lb;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
popup_write_screen(struct client *c, struct popup_data *pd)
 | 
			
		||||
{
 | 
			
		||||
	struct cmdq_item	*item = pd->item;
 | 
			
		||||
	struct screen_write_ctx	 ctx;
 | 
			
		||||
	char			*copy, *next, *loop, *tmp;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	u_int			 i, y;
 | 
			
		||||
 | 
			
		||||
	ft = format_create(item->client, item, FORMAT_NONE, 0);
 | 
			
		||||
	if (cmd_find_valid_state(&pd->fs))
 | 
			
		||||
		format_defaults(ft, c, pd->fs.s, pd->fs.wl, pd->fs.wp);
 | 
			
		||||
	else
 | 
			
		||||
		format_defaults(ft, c, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	screen_write_start(&ctx, NULL, &pd->s);
 | 
			
		||||
	screen_write_clearscreen(&ctx, 8);
 | 
			
		||||
 | 
			
		||||
	y = 0;
 | 
			
		||||
	for (i = 0; i < pd->nlines; i++) {
 | 
			
		||||
		if (y == pd->sy - 2)
 | 
			
		||||
			break;
 | 
			
		||||
		copy = next = xstrdup(pd->lines[i]);
 | 
			
		||||
		while ((loop = strsep(&next, "\n")) != NULL) {
 | 
			
		||||
			if (y == pd->sy - 2)
 | 
			
		||||
				break;
 | 
			
		||||
			tmp = format_expand(ft, loop);
 | 
			
		||||
			screen_write_cursormove(&ctx, 0, y, 0);
 | 
			
		||||
			format_draw(&ctx, &grid_default_cell, pd->sx - 2, tmp,
 | 
			
		||||
			    NULL);
 | 
			
		||||
			free(tmp);
 | 
			
		||||
			y++;
 | 
			
		||||
		}
 | 
			
		||||
		free(copy);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	format_free(ft);
 | 
			
		||||
	screen_write_cursormove(&ctx, 0, y, 0);
 | 
			
		||||
	screen_write_stop(&ctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
popup_mode_cb(struct client *c, u_int *cx, u_int *cy)
 | 
			
		||||
{
 | 
			
		||||
	struct popup_data	*pd = c->overlay_data;
 | 
			
		||||
 | 
			
		||||
	if (pd->ictx == NULL)
 | 
			
		||||
		return (0);
 | 
			
		||||
	*cx = pd->px + 1 + pd->s.cx;
 | 
			
		||||
	*cy = pd->py + 1 + pd->s.cy;
 | 
			
		||||
	return (pd->s.mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
popup_check_cb(struct client *c, u_int px, u_int py)
 | 
			
		||||
{
 | 
			
		||||
	struct popup_data	*pd = c->overlay_data;
 | 
			
		||||
 | 
			
		||||
	if (px < pd->px || px > pd->px + pd->sx - 1)
 | 
			
		||||
		return (1);
 | 
			
		||||
	if (py < pd->py || py > pd->py + pd->sy - 1)
 | 
			
		||||
		return (1);
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0)
 | 
			
		||||
{
 | 
			
		||||
	struct popup_data	*pd = c->overlay_data;
 | 
			
		||||
	struct tty		*tty = &c->tty;
 | 
			
		||||
	struct screen		 s;
 | 
			
		||||
	struct screen_write_ctx	 ctx;
 | 
			
		||||
	u_int			 i, px = pd->px, py = pd->py;
 | 
			
		||||
 | 
			
		||||
	screen_init(&s, pd->sx, pd->sy, 0);
 | 
			
		||||
	screen_write_start(&ctx, NULL, &s);
 | 
			
		||||
	screen_write_clearscreen(&ctx, 8);
 | 
			
		||||
	screen_write_box(&ctx, pd->sx, pd->sy);
 | 
			
		||||
	screen_write_cursormove(&ctx, 1, 1, 0);
 | 
			
		||||
	screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx - 2, pd->sy - 2);
 | 
			
		||||
	screen_write_stop(&ctx);
 | 
			
		||||
 | 
			
		||||
	c->overlay_check = NULL;
 | 
			
		||||
	for (i = 0; i < pd->sy; i++)
 | 
			
		||||
		tty_draw_line(tty, NULL, &s, 0, i, pd->sx, px, py + i);
 | 
			
		||||
	c->overlay_check = popup_check_cb;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
popup_free_cb(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	struct popup_data	*pd = c->overlay_data;
 | 
			
		||||
	struct cmdq_item	*item = pd->item;
 | 
			
		||||
	u_int			 i;
 | 
			
		||||
 | 
			
		||||
	if (item != NULL) {
 | 
			
		||||
		if (pd->ictx != NULL &&
 | 
			
		||||
		    item->client != NULL &&
 | 
			
		||||
		    item->client->session == NULL)
 | 
			
		||||
			item->client->retval = pd->status;
 | 
			
		||||
		cmdq_continue(item);
 | 
			
		||||
	}
 | 
			
		||||
	server_client_unref(pd->c);
 | 
			
		||||
 | 
			
		||||
	if (pd->job != NULL)
 | 
			
		||||
		job_free(pd->job);
 | 
			
		||||
	if (pd->ictx != NULL)
 | 
			
		||||
		input_free(pd->ictx);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < pd->nlines; i++)
 | 
			
		||||
		free(pd->lines[i]);
 | 
			
		||||
	free(pd->lines);
 | 
			
		||||
 | 
			
		||||
	screen_free(&pd->s);
 | 
			
		||||
	free(pd->cmd);
 | 
			
		||||
	free(pd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
popup_handle_drag(struct client *c, struct popup_data *pd,
 | 
			
		||||
    struct mouse_event *m)
 | 
			
		||||
{
 | 
			
		||||
	u_int	px, py;
 | 
			
		||||
 | 
			
		||||
	if (!MOUSE_DRAG(m->b))
 | 
			
		||||
		pd->dragging = OFF;
 | 
			
		||||
	else if (pd->dragging == MOVE) {
 | 
			
		||||
		if (m->x < pd->dx)
 | 
			
		||||
			px = 0;
 | 
			
		||||
		else if (m->x - pd->dx + pd->sx > c->tty.sx)
 | 
			
		||||
			px = c->tty.sx - pd->sx;
 | 
			
		||||
		else
 | 
			
		||||
			px = m->x - pd->dx;
 | 
			
		||||
		if (m->y < pd->dy)
 | 
			
		||||
			py = 0;
 | 
			
		||||
		else if (m->y - pd->dy + pd->sy > c->tty.sy)
 | 
			
		||||
			py = c->tty.sy - pd->sy;
 | 
			
		||||
		else
 | 
			
		||||
			py = m->y - pd->dy;
 | 
			
		||||
		pd->px = px;
 | 
			
		||||
		pd->py = py;
 | 
			
		||||
		pd->dx = m->x - pd->px;
 | 
			
		||||
		pd->dy = m->y - pd->py;
 | 
			
		||||
		server_redraw_client(c);
 | 
			
		||||
	} else if (pd->dragging == SIZE) {
 | 
			
		||||
		if (m->x < pd->px + 2)
 | 
			
		||||
			return;
 | 
			
		||||
		if (m->y < pd->py + 2)
 | 
			
		||||
			return;
 | 
			
		||||
		pd->sx = m->x - pd->px;
 | 
			
		||||
		pd->sy = m->y - pd->py;
 | 
			
		||||
 | 
			
		||||
		screen_resize(&pd->s, pd->sx, pd->sy, 0);
 | 
			
		||||
		if (pd->ictx == NULL)
 | 
			
		||||
			popup_write_screen(c, pd);
 | 
			
		||||
		else if (pd->job != NULL)
 | 
			
		||||
			job_resize(pd->job, pd->sx - 2, pd->sy - 2);
 | 
			
		||||
		server_redraw_client(c);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
popup_key_cb(struct client *c, struct key_event *event)
 | 
			
		||||
{
 | 
			
		||||
	struct popup_data	*pd = c->overlay_data;
 | 
			
		||||
	struct mouse_event	*m = &event->m;
 | 
			
		||||
	struct cmd_find_state	*fs = &pd->fs;
 | 
			
		||||
	struct cmdq_item	*new_item;
 | 
			
		||||
	struct cmd_parse_result	*pr;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	const char		*cmd;
 | 
			
		||||
 | 
			
		||||
	if (KEYC_IS_MOUSE(event->key)) {
 | 
			
		||||
		if (pd->dragging != OFF) {
 | 
			
		||||
			popup_handle_drag(c, pd, m);
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
		if (m->x < pd->px ||
 | 
			
		||||
		    m->x > pd->px + pd->sx - 1 ||
 | 
			
		||||
		    m->y < pd->py ||
 | 
			
		||||
		    m->y > pd->py + pd->sy - 1) {
 | 
			
		||||
			if (MOUSE_BUTTONS (m->b) == 1)
 | 
			
		||||
				return (1);
 | 
			
		||||
			return (0);
 | 
			
		||||
		}
 | 
			
		||||
		if ((m->b & MOUSE_MASK_META) ||
 | 
			
		||||
		    m->x == pd->px ||
 | 
			
		||||
		    m->x == pd->px + pd->sx - 1 ||
 | 
			
		||||
		    m->y == pd->py ||
 | 
			
		||||
		    m->y == pd->py + pd->sy - 1) {
 | 
			
		||||
			if (!MOUSE_DRAG(m->b))
 | 
			
		||||
				goto out;
 | 
			
		||||
			if (MOUSE_BUTTONS(m->lb) == 0)
 | 
			
		||||
				pd->dragging = MOVE;
 | 
			
		||||
			else if (MOUSE_BUTTONS(m->lb) == 2)
 | 
			
		||||
				pd->dragging = SIZE;
 | 
			
		||||
			pd->dx = m->lx - pd->px;
 | 
			
		||||
			pd->dy = m->ly - pd->py;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pd->ictx != NULL && (pd->flags & POPUP_WRITEKEYS)) {
 | 
			
		||||
		if (KEYC_IS_MOUSE(event->key))
 | 
			
		||||
			return (0);
 | 
			
		||||
		if ((~pd->flags & POPUP_CLOSEEXIT) &&
 | 
			
		||||
		    (event->key == '\033' || event->key == '\003'))
 | 
			
		||||
			return (1);
 | 
			
		||||
		if (pd->job == NULL)
 | 
			
		||||
			return (0);
 | 
			
		||||
		input_key(NULL, &pd->s, job_get_event(pd->job), event->key);
 | 
			
		||||
		return (0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pd->cmd == NULL)
 | 
			
		||||
		return (1);
 | 
			
		||||
 | 
			
		||||
	ft = format_create(NULL, pd->item, FORMAT_NONE, 0);
 | 
			
		||||
	if (cmd_find_valid_state(fs))
 | 
			
		||||
		format_defaults(ft, c, fs->s, fs->wl, fs->wp);
 | 
			
		||||
	else
 | 
			
		||||
		format_defaults(ft, c, NULL, NULL, NULL);
 | 
			
		||||
	format_add(ft, "popup_key", "%s", key_string_lookup_key(event->key));
 | 
			
		||||
	if (KEYC_IS_MOUSE(event->key)) {
 | 
			
		||||
		format_add(ft, "popup_mouse", "1");
 | 
			
		||||
		format_add(ft, "popup_mouse_x", "%u", m->x - pd->px);
 | 
			
		||||
		format_add(ft, "popup_mouse_y", "%u", m->y - pd->py);
 | 
			
		||||
	}
 | 
			
		||||
	cmd = format_expand(ft, pd->cmd);
 | 
			
		||||
	format_free(ft);
 | 
			
		||||
 | 
			
		||||
	pr = cmd_parse_from_string(cmd, NULL);
 | 
			
		||||
	switch (pr->status) {
 | 
			
		||||
	case CMD_PARSE_EMPTY:
 | 
			
		||||
		break;
 | 
			
		||||
	case CMD_PARSE_ERROR:
 | 
			
		||||
		new_item = cmdq_get_error(pr->error);
 | 
			
		||||
		free(pr->error);
 | 
			
		||||
		cmdq_append(c, new_item);
 | 
			
		||||
		break;
 | 
			
		||||
	case CMD_PARSE_SUCCESS:
 | 
			
		||||
		if (pd->item != NULL)
 | 
			
		||||
			m = &pd->item->shared->mouse;
 | 
			
		||||
		else
 | 
			
		||||
			m = NULL;
 | 
			
		||||
		new_item = cmdq_get_command(pr->cmdlist, fs, m, 0);
 | 
			
		||||
		cmd_list_free(pr->cmdlist);
 | 
			
		||||
		cmdq_append(c, new_item);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return (1);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	pd->lx = m->x;
 | 
			
		||||
	pd->ly = m->y;
 | 
			
		||||
	pd->lb = m->b;
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
popup_job_update_cb(struct job *job)
 | 
			
		||||
{
 | 
			
		||||
	struct popup_data	*pd = job_get_data(job);
 | 
			
		||||
	struct evbuffer		*evb = job_get_event(job)->input;
 | 
			
		||||
	struct screen		*s = &pd->s;
 | 
			
		||||
	void			*data = EVBUFFER_DATA(evb);
 | 
			
		||||
	size_t			 size = EVBUFFER_LENGTH(evb);
 | 
			
		||||
 | 
			
		||||
	if (size != 0) {
 | 
			
		||||
		input_parse_screen(pd->ictx, s, data, size);
 | 
			
		||||
		evbuffer_drain(evb, size);
 | 
			
		||||
		pd->c->flags |= CLIENT_REDRAWOVERLAY;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
popup_job_complete_cb(struct job *job)
 | 
			
		||||
{
 | 
			
		||||
	struct popup_data	*pd = job_get_data(job);
 | 
			
		||||
	int			 status;
 | 
			
		||||
 | 
			
		||||
	status = job_get_status(pd->job);
 | 
			
		||||
	if (WIFEXITED(status))
 | 
			
		||||
		pd->status = WEXITSTATUS(status);
 | 
			
		||||
	else if (WIFSIGNALED(status))
 | 
			
		||||
		pd->status = WTERMSIG(status);
 | 
			
		||||
	else
 | 
			
		||||
		pd->status = 0;
 | 
			
		||||
	pd->job = NULL;
 | 
			
		||||
 | 
			
		||||
	if (pd->flags & POPUP_CLOSEEXIT)
 | 
			
		||||
		server_client_clear_overlay(pd->c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u_int
 | 
			
		||||
popup_width(struct cmdq_item *item, u_int nlines, const char **lines,
 | 
			
		||||
    struct client *c, struct cmd_find_state *fs)
 | 
			
		||||
{
 | 
			
		||||
	char			*copy, *next, *loop, *tmp;
 | 
			
		||||
	struct format_tree	*ft;
 | 
			
		||||
	u_int			 i, width = 0, tmpwidth;
 | 
			
		||||
 | 
			
		||||
	ft = format_create(item->client, item, FORMAT_NONE, 0);
 | 
			
		||||
	if (fs != NULL && cmd_find_valid_state(fs))
 | 
			
		||||
		format_defaults(ft, c, fs->s, fs->wl, fs->wp);
 | 
			
		||||
	else
 | 
			
		||||
		format_defaults(ft, c, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < nlines; i++) {
 | 
			
		||||
		copy = next = xstrdup(lines[i]);
 | 
			
		||||
		while ((loop = strsep(&next, "\n")) != NULL) {
 | 
			
		||||
			tmp = format_expand(ft, loop);
 | 
			
		||||
			tmpwidth = format_width(tmp);
 | 
			
		||||
			if (tmpwidth > width)
 | 
			
		||||
				width = tmpwidth;
 | 
			
		||||
			free(tmp);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	free(copy);
 | 
			
		||||
 | 
			
		||||
	format_free(ft);
 | 
			
		||||
	return (width);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
 | 
			
		||||
    u_int sy, u_int nlines, const char **lines, const char *shellcmd,
 | 
			
		||||
    const char *cmd, const char *cwd, struct client *c,
 | 
			
		||||
    struct cmd_find_state *fs)
 | 
			
		||||
{
 | 
			
		||||
	struct popup_data	*pd;
 | 
			
		||||
	u_int			 i;
 | 
			
		||||
	struct session		*s;
 | 
			
		||||
	int			 jobflags;
 | 
			
		||||
 | 
			
		||||
	if (sx < 3 || sy < 3)
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if (c->tty.sx < sx || c->tty.sy < sy)
 | 
			
		||||
		return (-1);
 | 
			
		||||
	if (nlines > sy - 2)
 | 
			
		||||
		nlines = sy - 2;
 | 
			
		||||
 | 
			
		||||
	pd = xcalloc(1, sizeof *pd);
 | 
			
		||||
	pd->item = item;
 | 
			
		||||
	pd->flags = flags;
 | 
			
		||||
 | 
			
		||||
	pd->c = c;
 | 
			
		||||
	pd->c->references++;
 | 
			
		||||
 | 
			
		||||
	pd->status = 128 + SIGHUP;
 | 
			
		||||
 | 
			
		||||
	if (fs != NULL)
 | 
			
		||||
		cmd_find_copy_state(&pd->fs, fs);
 | 
			
		||||
	screen_init(&pd->s, sx - 2, sy - 2, 0);
 | 
			
		||||
 | 
			
		||||
	if (cmd != NULL)
 | 
			
		||||
		pd->cmd = xstrdup(cmd);
 | 
			
		||||
 | 
			
		||||
	pd->px = px;
 | 
			
		||||
	pd->py = py;
 | 
			
		||||
	pd->sx = sx;
 | 
			
		||||
	pd->sy = sy;
 | 
			
		||||
 | 
			
		||||
	pd->nlines = nlines;
 | 
			
		||||
	if (pd->nlines != 0)
 | 
			
		||||
		pd->lines = xreallocarray(NULL, pd->nlines, sizeof *pd->lines);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < pd->nlines; i++)
 | 
			
		||||
		pd->lines[i] = xstrdup(lines[i]);
 | 
			
		||||
	popup_write_screen(c, pd);
 | 
			
		||||
 | 
			
		||||
	if (shellcmd != NULL) {
 | 
			
		||||
		pd->ictx = input_init(NULL);
 | 
			
		||||
 | 
			
		||||
		if (fs != NULL)
 | 
			
		||||
			s = fs->s;
 | 
			
		||||
		else
 | 
			
		||||
			s = NULL;
 | 
			
		||||
		jobflags = JOB_NOWAIT|JOB_PTY;
 | 
			
		||||
		if (flags & POPUP_WRITEKEYS)
 | 
			
		||||
		    jobflags |= JOB_KEEPWRITE;
 | 
			
		||||
		pd->job = job_run(shellcmd, s, cwd, popup_job_update_cb,
 | 
			
		||||
		    popup_job_complete_cb, NULL, pd, jobflags, pd->sx - 2,
 | 
			
		||||
		    pd->sy - 2);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb,
 | 
			
		||||
	    popup_draw_cb, popup_key_cb, popup_free_cb, pd);
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
@@ -482,6 +482,8 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j,
 | 
			
		||||
	u_int			 type, x = ctx->ox + i, y = ctx->oy + j;
 | 
			
		||||
	int			 flag, pane_status = ctx->pane_status;
 | 
			
		||||
 | 
			
		||||
	if (c->overlay_check != NULL && !c->overlay_check(c, x, y))
 | 
			
		||||
		return;
 | 
			
		||||
	type = screen_redraw_check_cell(c, x, y, pane_status, &wp);
 | 
			
		||||
	if (type == CELL_INSIDE)
 | 
			
		||||
		return;
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,6 @@ static void	server_client_check_redraw(struct client *);
 | 
			
		||||
static void	server_client_set_title(struct client *);
 | 
			
		||||
static void	server_client_reset_state(struct client *);
 | 
			
		||||
static int	server_client_assume_paste(struct session *);
 | 
			
		||||
static void	server_client_clear_overlay(struct client *);
 | 
			
		||||
static void	server_client_resize_event(int, short, void *);
 | 
			
		||||
 | 
			
		||||
static void	server_client_dispatch(struct imsg *, void *);
 | 
			
		||||
@@ -79,8 +78,10 @@ server_client_overlay_timer(__unused int fd, __unused short events, void *data)
 | 
			
		||||
 | 
			
		||||
/* Set an overlay on client. */
 | 
			
		||||
void
 | 
			
		||||
server_client_set_overlay(struct client *c, u_int delay, overlay_draw_cb drawcb,
 | 
			
		||||
    overlay_key_cb keycb, overlay_free_cb freecb, void *data)
 | 
			
		||||
server_client_set_overlay(struct client *c, u_int delay,
 | 
			
		||||
    overlay_check_cb checkcb, overlay_mode_cb modecb,
 | 
			
		||||
    overlay_draw_cb drawcb, overlay_key_cb keycb, overlay_free_cb freecb,
 | 
			
		||||
    void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct timeval	tv;
 | 
			
		||||
 | 
			
		||||
@@ -96,17 +97,21 @@ server_client_set_overlay(struct client *c, u_int delay, overlay_draw_cb drawcb,
 | 
			
		||||
	if (delay != 0)
 | 
			
		||||
		evtimer_add(&c->overlay_timer, &tv);
 | 
			
		||||
 | 
			
		||||
	c->overlay_check = checkcb;
 | 
			
		||||
	c->overlay_mode = modecb;
 | 
			
		||||
	c->overlay_draw = drawcb;
 | 
			
		||||
	c->overlay_key = keycb;
 | 
			
		||||
	c->overlay_free = freecb;
 | 
			
		||||
	c->overlay_data = data;
 | 
			
		||||
 | 
			
		||||
	c->tty.flags |= (TTY_FREEZE|TTY_NOCURSOR);
 | 
			
		||||
	c->tty.flags |= TTY_FREEZE;
 | 
			
		||||
	if (c->overlay_mode == NULL)
 | 
			
		||||
		c->tty.flags |= TTY_NOCURSOR;
 | 
			
		||||
	server_redraw_client(c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Clear overlay mode on client. */
 | 
			
		||||
static void
 | 
			
		||||
void
 | 
			
		||||
server_client_clear_overlay(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	if (c->overlay_draw == NULL)
 | 
			
		||||
@@ -118,8 +123,12 @@ server_client_clear_overlay(struct client *c)
 | 
			
		||||
	if (c->overlay_free != NULL)
 | 
			
		||||
		c->overlay_free(c);
 | 
			
		||||
 | 
			
		||||
	c->overlay_check = NULL;
 | 
			
		||||
	c->overlay_mode = NULL;
 | 
			
		||||
	c->overlay_draw = NULL;
 | 
			
		||||
	c->overlay_key = NULL;
 | 
			
		||||
	c->overlay_free = NULL;
 | 
			
		||||
	c->overlay_data = NULL;
 | 
			
		||||
 | 
			
		||||
	c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
 | 
			
		||||
	server_redraw_client(c);
 | 
			
		||||
@@ -1483,21 +1492,33 @@ server_client_reset_state(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	struct window		*w = c->session->curw->window;
 | 
			
		||||
	struct window_pane	*wp = w->active, *loop;
 | 
			
		||||
	struct screen		*s = wp->screen;
 | 
			
		||||
	struct screen		*s;
 | 
			
		||||
	struct options		*oo = c->session->options;
 | 
			
		||||
	int			 mode, cursor = 0;
 | 
			
		||||
	u_int			 cx = 0, cy = 0, ox, oy, sx, sy;
 | 
			
		||||
 | 
			
		||||
	if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
 | 
			
		||||
		return;
 | 
			
		||||
	if (c->overlay_draw != NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	mode = s->mode;
 | 
			
		||||
 | 
			
		||||
	/* Get mode from overlay if any, else from screen. */
 | 
			
		||||
	if (c->overlay_draw != NULL) {
 | 
			
		||||
		s = NULL;
 | 
			
		||||
		if (c->overlay_mode == NULL)
 | 
			
		||||
			mode = 0;
 | 
			
		||||
		else
 | 
			
		||||
			mode = c->overlay_mode(c, &cx, &cy);
 | 
			
		||||
	} else {
 | 
			
		||||
		s = wp->screen;
 | 
			
		||||
		mode = s->mode;
 | 
			
		||||
	}
 | 
			
		||||
	log_debug("%s: client %s mode %x", __func__, c->name, mode);
 | 
			
		||||
 | 
			
		||||
	/* Reset region and margin. */
 | 
			
		||||
	tty_region_off(&c->tty);
 | 
			
		||||
	tty_margin_off(&c->tty);
 | 
			
		||||
 | 
			
		||||
	/* Move cursor to pane cursor and offset. */
 | 
			
		||||
	if (c->overlay_draw == NULL) {
 | 
			
		||||
		cursor = 0;
 | 
			
		||||
		tty_window_offset(&c->tty, &ox, &oy, &sx, &sy);
 | 
			
		||||
		if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx &&
 | 
			
		||||
@@ -1512,6 +1533,7 @@ server_client_reset_state(struct client *c)
 | 
			
		||||
		}
 | 
			
		||||
		if (!cursor)
 | 
			
		||||
			mode &= ~MODE_CURSOR;
 | 
			
		||||
	}
 | 
			
		||||
	tty_cursor(&c->tty, cx, cy);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
@@ -1520,16 +1542,18 @@ server_client_reset_state(struct client *c)
 | 
			
		||||
	 */
 | 
			
		||||
	if (options_get_number(oo, "mouse")) {
 | 
			
		||||
		mode &= ~ALL_MOUSE_MODES;
 | 
			
		||||
		if (c->overlay_draw == NULL) {
 | 
			
		||||
			TAILQ_FOREACH(loop, &w->panes, entry) {
 | 
			
		||||
				if (loop->screen->mode & MODE_MOUSE_ALL)
 | 
			
		||||
					mode |= MODE_MOUSE_ALL;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (~mode & MODE_MOUSE_ALL)
 | 
			
		||||
			mode |= MODE_MOUSE_BUTTON;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Clear bracketed paste mode if at the prompt. */
 | 
			
		||||
	if (c->prompt_string != NULL)
 | 
			
		||||
	if (c->overlay_draw == NULL && c->prompt_string != NULL)
 | 
			
		||||
		mode &= ~MODE_BRACKETPASTE;
 | 
			
		||||
 | 
			
		||||
	/* Set the terminal mode and reset attributes. */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										89
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								tmux.1
									
									
									
									
									
								
							@@ -4384,6 +4384,9 @@ The following variables are available, where appropriate:
 | 
			
		||||
.It Li "pane_tty" Ta "" Ta "Pseudo terminal of pane"
 | 
			
		||||
.It Li "pane_width" Ta "" Ta "Width of pane"
 | 
			
		||||
.It Li "pid" Ta "" Ta "Server PID"
 | 
			
		||||
.It Li "popup_key" Ta "" Ta "Key pressed in popup"
 | 
			
		||||
.It Li "popup_mouse_x" Ta "" Ta "Mouse X position in popup"
 | 
			
		||||
.It Li "popup_mouse_y" Ta "" Ta "Mouse Y position in popup"
 | 
			
		||||
.It Li "rectangle_toggle" Ta "" Ta "1 if rectangle selection is activated"
 | 
			
		||||
.It Li "scroll_position" Ta "" Ta "Scroll position in copy mode"
 | 
			
		||||
.It Li "scroll_region_lower" Ta "" Ta "Bottom of scroll region in pane"
 | 
			
		||||
@@ -4973,6 +4976,92 @@ lists the format variables and their values.
 | 
			
		||||
.Fl I
 | 
			
		||||
forwards any input read from stdin to the empty pane given by
 | 
			
		||||
.Ar target-pane .
 | 
			
		||||
.It Xo Ic display-popup
 | 
			
		||||
.Op Fl CEK
 | 
			
		||||
.Op Fl c Ar target-client
 | 
			
		||||
.Op Fl d Ar start-directory
 | 
			
		||||
.Op Fl h Ar height
 | 
			
		||||
.Op Fl R Ar shell-command
 | 
			
		||||
.Op Fl t Ar target-pane
 | 
			
		||||
.Op Fl w Ar width
 | 
			
		||||
.Op Fl x Ar position
 | 
			
		||||
.Op Fl y Ar position
 | 
			
		||||
.Op Ar command Ar line Ar ...
 | 
			
		||||
.Xc
 | 
			
		||||
.D1 (alias: Ic popup )
 | 
			
		||||
Display a popup on
 | 
			
		||||
.Ar target-client .
 | 
			
		||||
A popup is a rectangular box drawn over the top of any panes.
 | 
			
		||||
Panes are not updated while a popup is present.
 | 
			
		||||
The popup content may be given in two ways:
 | 
			
		||||
.Bl -enum -offset Ds
 | 
			
		||||
.It
 | 
			
		||||
A set of lines as arguments.
 | 
			
		||||
Each line is a format which is expanded using
 | 
			
		||||
.Ar target-pane
 | 
			
		||||
as the target.
 | 
			
		||||
If a line contains newlines it is split into multiple lines.
 | 
			
		||||
Lines may use styles, see the
 | 
			
		||||
.Sx STYLES
 | 
			
		||||
section.
 | 
			
		||||
.It
 | 
			
		||||
A shell command given by
 | 
			
		||||
.Fl R
 | 
			
		||||
which is run and any output shown in the pane.
 | 
			
		||||
.El
 | 
			
		||||
.Pp
 | 
			
		||||
The first argument,
 | 
			
		||||
.Ar command ,
 | 
			
		||||
is a
 | 
			
		||||
.Nm
 | 
			
		||||
command which is run when a key is pressed.
 | 
			
		||||
The key is available in the
 | 
			
		||||
.Ql popup_key
 | 
			
		||||
format.
 | 
			
		||||
After
 | 
			
		||||
.Ar command
 | 
			
		||||
is run, the popup is closed.
 | 
			
		||||
It may be empty to discard any key presses.
 | 
			
		||||
If
 | 
			
		||||
.Fl K
 | 
			
		||||
is given together with
 | 
			
		||||
.Fl R,
 | 
			
		||||
key presses are instead passed to the
 | 
			
		||||
.Fl R
 | 
			
		||||
shell command.
 | 
			
		||||
.Fl E
 | 
			
		||||
closes the popup automatically when
 | 
			
		||||
.Ar shell-command
 | 
			
		||||
exits.
 | 
			
		||||
With
 | 
			
		||||
.Fl K ,
 | 
			
		||||
.Ql Escape
 | 
			
		||||
and
 | 
			
		||||
.Ql C-c
 | 
			
		||||
close the popup unless
 | 
			
		||||
.Fl E
 | 
			
		||||
is also given.
 | 
			
		||||
.Pp
 | 
			
		||||
.Fl x
 | 
			
		||||
and
 | 
			
		||||
.Fl y
 | 
			
		||||
give the position of the popup, they have the same meaning as for the
 | 
			
		||||
.Ic display-menu
 | 
			
		||||
command.
 | 
			
		||||
.Fl w
 | 
			
		||||
and
 | 
			
		||||
.Fl h
 | 
			
		||||
give the width and height - both may be a percentage (followed by
 | 
			
		||||
.Ql % ) .
 | 
			
		||||
If omitted, without
 | 
			
		||||
.Fl R
 | 
			
		||||
they are calculated from the given lines and with
 | 
			
		||||
.Fl R
 | 
			
		||||
they use half the terminal size.
 | 
			
		||||
.Pp
 | 
			
		||||
The
 | 
			
		||||
.Fl C
 | 
			
		||||
flag closes any popup on the client.
 | 
			
		||||
.El
 | 
			
		||||
.Sh BUFFERS
 | 
			
		||||
.Nm
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1517,6 +1517,8 @@ RB_HEAD(client_files, client_file);
 | 
			
		||||
/* Client connection. */
 | 
			
		||||
typedef int (*prompt_input_cb)(struct client *, void *, const char *, int);
 | 
			
		||||
typedef void (*prompt_free_cb)(void *);
 | 
			
		||||
typedef int (*overlay_check_cb)(struct client *, u_int, u_int);
 | 
			
		||||
typedef int (*overlay_mode_cb)(struct client *, u_int *, u_int *);
 | 
			
		||||
typedef void (*overlay_draw_cb)(struct client *, struct screen_redraw_ctx *);
 | 
			
		||||
typedef int (*overlay_key_cb)(struct client *, struct key_event *);
 | 
			
		||||
typedef void (*overlay_free_cb)(struct client *);
 | 
			
		||||
@@ -1632,6 +1634,8 @@ struct client {
 | 
			
		||||
	u_int		 pan_ox;
 | 
			
		||||
	u_int		 pan_oy;
 | 
			
		||||
 | 
			
		||||
	overlay_check_cb overlay_check;
 | 
			
		||||
	overlay_mode_cb	 overlay_mode;
 | 
			
		||||
	overlay_draw_cb	 overlay_draw;
 | 
			
		||||
	overlay_key_cb	 overlay_key;
 | 
			
		||||
	overlay_free_cb	 overlay_free;
 | 
			
		||||
@@ -1936,6 +1940,7 @@ struct job	*job_run(const char *, struct session *, const char *,
 | 
			
		||||
		     job_update_cb, job_complete_cb, job_free_cb, void *, int,
 | 
			
		||||
		     int, int);
 | 
			
		||||
void		 job_free(struct job *);
 | 
			
		||||
void		 job_resize(struct job *, u_int, u_int);
 | 
			
		||||
void		 job_check_died(pid_t, int);
 | 
			
		||||
int		 job_get_status(struct job *);
 | 
			
		||||
void		*job_get_data(struct job *);
 | 
			
		||||
@@ -2218,8 +2223,10 @@ void	 server_add_accept(int);
 | 
			
		||||
 | 
			
		||||
/* server-client.c */
 | 
			
		||||
u_int	 server_client_how_many(void);
 | 
			
		||||
void	 server_client_set_overlay(struct client *, u_int, overlay_draw_cb,
 | 
			
		||||
    overlay_key_cb, overlay_free_cb, void *);
 | 
			
		||||
void	 server_client_set_overlay(struct client *, u_int, overlay_check_cb,
 | 
			
		||||
	     overlay_mode_cb, overlay_draw_cb, overlay_key_cb,
 | 
			
		||||
	     overlay_free_cb, void *);
 | 
			
		||||
void	 server_client_clear_overlay(struct client *);
 | 
			
		||||
void	 server_client_set_key_table(struct client *, const char *);
 | 
			
		||||
const char *server_client_get_key_table(struct client *);
 | 
			
		||||
int	 server_client_check_nested(struct client *);
 | 
			
		||||
@@ -2755,6 +2762,15 @@ int		 menu_display(struct menu *, int, struct cmdq_item *, u_int,
 | 
			
		||||
		    u_int, struct client *, struct cmd_find_state *,
 | 
			
		||||
		    menu_choice_cb, void *);
 | 
			
		||||
 | 
			
		||||
/* popup.c */
 | 
			
		||||
#define POPUP_WRITEKEYS 0x1
 | 
			
		||||
#define POPUP_CLOSEEXIT 0x2
 | 
			
		||||
u_int		 popup_width(struct cmdq_item *, u_int, const char **,
 | 
			
		||||
		    struct client *, struct cmd_find_state *);
 | 
			
		||||
int		 popup_display(int, struct cmdq_item *, u_int, u_int, u_int,
 | 
			
		||||
		    u_int, u_int, const char **, const char *, const char *,
 | 
			
		||||
		    const char *, struct client *, struct cmd_find_state *);
 | 
			
		||||
 | 
			
		||||
/* style.c */
 | 
			
		||||
int		 style_parse(struct style *,const struct grid_cell *,
 | 
			
		||||
		     const char *);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								tty.c
									
									
									
									
									
								
							@@ -1250,6 +1250,16 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
 | 
			
		||||
	return (&new);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
tty_check_overlay(struct tty *tty, u_int px, u_int py)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c = tty->client;
 | 
			
		||||
 | 
			
		||||
	if (c->overlay_check == NULL)
 | 
			
		||||
		return (1);
 | 
			
		||||
	return (c->overlay_check(c, px, py));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
 | 
			
		||||
    u_int px, u_int py, u_int nx, u_int atx, u_int aty)
 | 
			
		||||
@@ -1329,7 +1339,8 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
 | 
			
		||||
		grid_view_get_cell(gd, px + i, py, &gc);
 | 
			
		||||
		gcp = tty_check_codeset(tty, &gc);
 | 
			
		||||
		if (len != 0 &&
 | 
			
		||||
		    ((gcp->attr & GRID_ATTR_CHARSET) ||
 | 
			
		||||
		    (!tty_check_overlay(tty, atx + ux + width, aty) ||
 | 
			
		||||
		    (gcp->attr & GRID_ATTR_CHARSET) ||
 | 
			
		||||
		    gcp->flags != last.flags ||
 | 
			
		||||
		    gcp->attr != last.attr ||
 | 
			
		||||
		    gcp->fg != last.fg ||
 | 
			
		||||
@@ -1358,7 +1369,9 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
 | 
			
		||||
			screen_select_cell(s, &last, gcp);
 | 
			
		||||
		else
 | 
			
		||||
			memcpy(&last, gcp, sizeof last);
 | 
			
		||||
		if (ux + gcp->data.width > nx) {
 | 
			
		||||
		if (!tty_check_overlay(tty, atx + ux, aty))
 | 
			
		||||
			ux += gcp->data.width;
 | 
			
		||||
		else if (ux + gcp->data.width > nx) {
 | 
			
		||||
			tty_attributes(tty, &last, wp);
 | 
			
		||||
			tty_cursor(tty, atx + ux, aty);
 | 
			
		||||
			for (j = 0; j < gcp->data.width; j++) {
 | 
			
		||||
@@ -1372,7 +1385,7 @@ tty_draw_line(struct tty *tty, struct window_pane *wp, struct screen *s,
 | 
			
		||||
			tty_cursor(tty, atx + ux, aty);
 | 
			
		||||
			for (j = 0; j < gcp->data.size; j++)
 | 
			
		||||
				tty_putc(tty, gcp->data.data[j]);
 | 
			
		||||
			ux += gc.data.width;
 | 
			
		||||
			ux += gcp->data.width;
 | 
			
		||||
		} else {
 | 
			
		||||
			memcpy(buf + len, gcp->data.data, gcp->data.size);
 | 
			
		||||
			len += gcp->data.size;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user