summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd-display-menu.c2
-rw-r--r--cmd-display-panes.c4
-rw-r--r--menu.c2
-rw-r--r--popup.c64
-rw-r--r--server-client.c8
-rw-r--r--tmux.h4
6 files changed, 73 insertions, 11 deletions
diff --git a/cmd-display-menu.c b/cmd-display-menu.c
index 91a7aa4d..92def23b 100644
--- a/cmd-display-menu.c
+++ b/cmd-display-menu.c
@@ -174,7 +174,7 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
} else
format_add(ft, "popup_mouse_centre_y", "%ld", n);
n = (long)event->m.y + h;
- if (n + h >= tty->sy)
+ if (n >= tty->sy)
format_add(ft, "popup_mouse_top", "%u", tty->sy - 1);
else
format_add(ft, "popup_mouse_top", "%ld", n);
diff --git a/cmd-display-panes.c b/cmd-display-panes.c
index 64efb89a..f03b80ed 100644
--- a/cmd-display-panes.c
+++ b/cmd-display-panes.c
@@ -286,12 +286,12 @@ cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 'N')) {
server_client_set_overlay(tc, delay, NULL, NULL,
- cmd_display_panes_draw, NULL, cmd_display_panes_free,
+ cmd_display_panes_draw, NULL, cmd_display_panes_free, NULL,
cdata);
} else {
server_client_set_overlay(tc, delay, NULL, NULL,
cmd_display_panes_draw, cmd_display_panes_key,
- cmd_display_panes_free, cdata);
+ cmd_display_panes_free, NULL, cdata);
}
if (args_has(args, 'b'))
diff --git a/menu.c b/menu.c
index 48c9ed2f..c8de02a8 100644
--- a/menu.c
+++ b/menu.c
@@ -390,6 +390,6 @@ menu_display(struct menu *menu, int flags, struct cmdq_item *item, u_int px,
md->data = data;
server_client_set_overlay(c, 0, NULL, menu_mode_cb, menu_draw_cb,
- menu_key_cb, menu_free_cb, md);
+ menu_key_cb, menu_free_cb, NULL, md);
return (0);
}
diff --git a/popup.c b/popup.c
index 509d182d..e5f92bad 100644
--- a/popup.c
+++ b/popup.c
@@ -38,11 +38,18 @@ struct popup_data {
popup_close_cb cb;
void *arg;
+ /* Current position and size. */
u_int px;
u_int py;
u_int sx;
u_int sy;
+ /* Preferred position and size. */
+ u_int ppx;
+ u_int ppy;
+ u_int psx;
+ u_int psy;
+
enum { OFF, MOVE, SIZE } dragging;
u_int dx;
u_int dy;
@@ -132,9 +139,14 @@ popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0)
screen_init(&s, pd->sx, pd->sy, 0);
screen_write_start(&ctx, &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);
+
+ /* Skip drawing popup if the terminal is too small. */
+ if (pd->sx > 2 && pd->sy > 2) {
+ 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;
@@ -171,6 +183,41 @@ popup_free_cb(struct client *c)
}
static void
+popup_resize_cb(struct client *c)
+{
+ struct popup_data *pd = c->overlay_data;
+ struct tty *tty = &c->tty;
+
+ if (pd == NULL)
+ return;
+
+ /* Adjust position and size. */
+ if (pd->psy > tty->sy)
+ pd->sy = tty->sy;
+ else
+ pd->sy = pd->psy;
+ if (pd->psx > tty->sx)
+ pd->sx = tty->sx;
+ else
+ pd->sx = pd->psx;
+ if (pd->ppy + pd->sy > tty->sy)
+ pd->py = tty->sy - pd->sy;
+ else
+ pd->py = pd->ppy;
+ if (pd->ppx + pd->sx > tty->sx)
+ pd->px = tty->sx - pd->sx;
+ else
+ pd->px = pd->ppx;
+
+ /* Avoid zero size screens. */
+ if (pd->sx > 2 && pd->sy > 2) {
+ screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 0);
+ if (pd->job != NULL)
+ job_resize(pd->job, pd->sx - 2, pd->sy - 2);
+ }
+}
+
+static void
popup_handle_drag(struct client *c, struct popup_data *pd,
struct mouse_event *m)
{
@@ -195,6 +242,8 @@ popup_handle_drag(struct client *c, struct popup_data *pd,
pd->py = py;
pd->dx = m->x - pd->px;
pd->dy = m->y - pd->py;
+ pd->ppx = px;
+ pd->ppy = py;
server_redraw_client(c);
} else if (pd->dragging == SIZE) {
if (m->x < pd->px + 3)
@@ -203,6 +252,8 @@ popup_handle_drag(struct client *c, struct popup_data *pd,
return;
pd->sx = m->x - pd->px;
pd->sy = m->y - pd->py;
+ pd->psx = pd->sx;
+ pd->psy = pd->sy;
screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 0);
if (pd->job != NULL)
@@ -347,13 +398,18 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx,
pd->sx = sx;
pd->sy = sy;
+ pd->ppx = px;
+ pd->ppy = py;
+ pd->psx = sx;
+ pd->psy = sy;
+
pd->job = job_run(shellcmd, argc, argv, s, cwd,
popup_job_update_cb, popup_job_complete_cb, NULL, pd,
JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, pd->sx - 2, pd->sy - 2);
pd->ictx = input_init(NULL, job_get_event(pd->job));
server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb,
- popup_draw_cb, popup_key_cb, popup_free_cb, pd);
+ popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd);
return (0);
}
diff --git a/server-client.c b/server-client.c
index e3a690bd..15d86077 100644
--- a/server-client.c
+++ b/server-client.c
@@ -90,7 +90,7 @@ void
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)
+ overlay_resize_cb resizecb, void *data)
{
struct timeval tv;
@@ -111,6 +111,7 @@ server_client_set_overlay(struct client *c, u_int delay,
c->overlay_draw = drawcb;
c->overlay_key = keycb;
c->overlay_free = freecb;
+ c->overlay_resize = resizecb;
c->overlay_data = data;
c->tty.flags |= TTY_FREEZE;
@@ -2058,9 +2059,12 @@ server_client_dispatch(struct imsg *imsg, void *arg)
if (c->flags & CLIENT_CONTROL)
break;
server_client_update_latest(c);
- server_client_clear_overlay(c);
tty_resize(&c->tty);
recalculate_sizes();
+ if (c->overlay_resize == NULL)
+ server_client_clear_overlay(c);
+ else
+ c->overlay_resize(c);
server_redraw_client(c);
if (c->session != NULL)
notify_client("client-resized", c);
diff --git a/tmux.h b/tmux.h
index beaec718..e23044ba 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1630,6 +1630,7 @@ typedef struct screen *(*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 *);
+typedef void (*overlay_resize_cb)(struct client *);
struct client {
const char *name;
struct tmuxpeer *peer;
@@ -1777,6 +1778,7 @@ struct client {
overlay_draw_cb overlay_draw;
overlay_key_cb overlay_key;
overlay_free_cb overlay_free;
+ overlay_resize_cb overlay_resize;
void *overlay_data;
struct event overlay_timer;
@@ -2484,7 +2486,7 @@ RB_PROTOTYPE(client_windows, client_window, entry, server_client_window_cmp);
u_int server_client_how_many(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 *);
+ overlay_free_cb, overlay_resize_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 *);