mirror of
https://github.com/tmux/tmux.git
synced 2026-03-11 19:15:45 +00:00
Compare commits
103 Commits
ta/kitty-i
...
floating_p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a90fce476 | ||
|
|
e928e80a42 | ||
|
|
28c04b21f6 | ||
|
|
46427f1dd7 | ||
|
|
528e856566 | ||
|
|
14a934d412 | ||
|
|
d0caf0a322 | ||
|
|
91b5108eae | ||
|
|
2c7f73f9c4 | ||
|
|
5310592967 | ||
|
|
41bddae907 | ||
|
|
0faed7aeb5 | ||
|
|
8e6450c8fc | ||
|
|
6898e26a7a | ||
|
|
e2cf40ef99 | ||
|
|
96515c9f47 | ||
|
|
96e18faa93 | ||
|
|
476c6e89ad | ||
|
|
b46a96d454 | ||
|
|
f67cf7d053 | ||
|
|
2ad0f4a9e7 | ||
|
|
1ec9ca497b | ||
|
|
dd5d0f4f0c | ||
|
|
d1a6ce8e7f | ||
|
|
b22537e8a4 | ||
|
|
a25c14d472 | ||
|
|
7730d38339 | ||
|
|
58e498c9d3 | ||
|
|
35485f2b5e | ||
|
|
b108653f02 | ||
|
|
25f72cf240 | ||
|
|
d1df8dcccc | ||
|
|
a50d00aa47 | ||
|
|
34add944f2 | ||
|
|
95f85efc49 | ||
|
|
f2f6a05e2c | ||
|
|
bd442a27ee | ||
|
|
73c0eb96c3 | ||
|
|
6a4a4a432b | ||
|
|
263529e886 | ||
|
|
818797ff08 | ||
|
|
d263dbe9dd | ||
|
|
67319ad9d9 | ||
|
|
2591df66cc | ||
|
|
2ac78bccb5 | ||
|
|
47de44001e | ||
|
|
eaa467618b | ||
|
|
ac01f15bfe | ||
|
|
5df5217e2e | ||
|
|
a6ec2b76c2 | ||
|
|
bc01b300c4 | ||
|
|
c8d4d8cb66 | ||
|
|
315202b007 | ||
|
|
7194fdca38 | ||
|
|
31d0945059 | ||
|
|
466e79d572 | ||
|
|
3bb4f72a4b | ||
|
|
329e9d54ab | ||
|
|
9c45dd693b | ||
|
|
cc671e4495 | ||
|
|
61ca158de1 | ||
|
|
7e0038c691 | ||
|
|
04792d0656 | ||
|
|
6c5cc40039 | ||
|
|
6b462474f0 | ||
|
|
9a061a2fee | ||
|
|
6dd552d689 | ||
|
|
34e858ea05 | ||
|
|
39d2839e37 | ||
|
|
7980d00e8c | ||
|
|
25ce5b4281 | ||
|
|
0cd3ab6299 | ||
|
|
28d038fb16 | ||
|
|
10dc308e6b | ||
|
|
6344bab6cc | ||
|
|
984fbacccf | ||
|
|
cc83ca6628 | ||
|
|
04fc6ea11b | ||
|
|
8a9e2fccbd | ||
|
|
cc1324e2d9 | ||
|
|
b2226d1608 | ||
|
|
8ce0af3fc9 | ||
|
|
b315a6c3d1 | ||
|
|
baf642b7d2 | ||
|
|
8db76e9057 | ||
|
|
e3b7bf9b31 | ||
|
|
38724f2e86 | ||
|
|
65fc09fac9 | ||
|
|
3197b715b3 | ||
|
|
26362dfc72 | ||
|
|
275781ce45 | ||
|
|
72dbbfedce | ||
|
|
a6c6eabb5a | ||
|
|
379e4d976c | ||
|
|
a6514e2656 | ||
|
|
032af23e18 | ||
|
|
b5f9293014 | ||
|
|
a37db55689 | ||
|
|
1b959d0eff | ||
|
|
ce03f1abea | ||
|
|
5faf41b695 | ||
|
|
7634daa834 | ||
|
|
968f439672 |
14
Makefile.am
14
Makefile.am
@@ -113,7 +113,9 @@ dist_tmux_SOURCES = \
|
||||
cmd-list-windows.c \
|
||||
cmd-load-buffer.c \
|
||||
cmd-lock-server.c \
|
||||
cmd-minimise-pane.c \
|
||||
cmd-move-window.c \
|
||||
cmd-new-pane.c \
|
||||
cmd-new-session.c \
|
||||
cmd-new-window.c \
|
||||
cmd-parse.y \
|
||||
@@ -232,18 +234,8 @@ nodist_tmux_SOURCES += compat/utf8proc.c
|
||||
endif
|
||||
|
||||
# Enable sixel support.
|
||||
if ENABLE_SIXEL_IMAGES
|
||||
if ENABLE_SIXEL
|
||||
dist_tmux_SOURCES += image.c image-sixel.c
|
||||
else
|
||||
# If not sixel, still need image.c for kitty.
|
||||
if ENABLE_KITTY_IMAGES
|
||||
dist_tmux_SOURCES += image.c
|
||||
endif
|
||||
endif
|
||||
|
||||
# Enable kitty graphics protocol support.
|
||||
if ENABLE_KITTY_IMAGES
|
||||
dist_tmux_SOURCES += image-kitty.c
|
||||
endif
|
||||
|
||||
if NEED_FUZZING
|
||||
|
||||
@@ -63,6 +63,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct client *c = cmdq_get_client(item);
|
||||
struct session *s;
|
||||
struct window_pane *wp = target->wp, *swp;
|
||||
u_int tty_ox, tty_oy, tty_sx, tty_sy;
|
||||
|
||||
if (args_has(args, 'q')) {
|
||||
window_pane_reset_mode_all(wp);
|
||||
@@ -94,8 +95,9 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (args_has(args, 'd'))
|
||||
window_copy_pagedown(wp, 0, args_has(args, 'e'));
|
||||
if (args_has(args, 'S')) {
|
||||
tty_window_offset(&c->tty, &tty_ox, &tty_oy, &tty_sx, &tty_sy);
|
||||
window_copy_scroll(wp, c->tty.mouse_slider_mpos, event->m.y,
|
||||
args_has(args, 'e'));
|
||||
tty_oy, args_has(args, 'e'));
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
|
||||
@@ -370,7 +370,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
|
||||
flags |= MENU_NOMOUSE;
|
||||
if (menu_display(menu, flags, starting_choice, item, px, py, tc, lines,
|
||||
style, selected_style, border_style, target, NULL, NULL) != 0)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
goto out;
|
||||
return (CMD_RETURN_WAIT);
|
||||
|
||||
out:
|
||||
|
||||
@@ -70,10 +70,10 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
|
||||
char buf[16], lbuf[16], rbuf[16], *ptr;
|
||||
size_t len, llen, rlen;
|
||||
|
||||
if (wp->xoff + wp->sx <= ctx->ox ||
|
||||
wp->xoff >= ctx->ox + ctx->sx ||
|
||||
wp->yoff + wp->sy <= ctx->oy ||
|
||||
wp->yoff >= ctx->oy + ctx->sy)
|
||||
if (wp->xoff + (int)wp->sx <= ctx->ox ||
|
||||
wp->xoff >= ctx->ox + (int)ctx->sx ||
|
||||
wp->yoff + (int)wp->sy <= ctx->oy ||
|
||||
wp->yoff >= ctx->oy + (int)ctx->sy)
|
||||
return;
|
||||
|
||||
if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
|
||||
|
||||
@@ -978,15 +978,20 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
||||
} else if (cmd_find_from_client(¤t, cmdq_get_client(item),
|
||||
flags) == 0) {
|
||||
fs->current = ¤t;
|
||||
/* No active pane, window empty, return the window instead. */
|
||||
if (current.wp == NULL) {
|
||||
type = CMD_FIND_WINDOW;
|
||||
}
|
||||
log_debug("%s: current is from client", __func__);
|
||||
} else {
|
||||
if (~flags & CMD_FIND_QUIET)
|
||||
cmdq_error(item, "no current target");
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
if (!cmd_find_valid_state(fs->current))
|
||||
fatalx("invalid current find state");
|
||||
|
||||
*/
|
||||
/* An empty or NULL target is the current. */
|
||||
if (target == NULL || *target == '\0')
|
||||
goto current;
|
||||
@@ -1025,7 +1030,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
|
||||
fs->w = fs->wl->window;
|
||||
fs->wp = fs->w->active;
|
||||
}
|
||||
break;
|
||||
goto found;
|
||||
}
|
||||
if (fs->wp == NULL) {
|
||||
if (~flags & CMD_FIND_QUIET)
|
||||
|
||||
@@ -62,6 +62,11 @@ cmd_kill_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
if (wp == NULL) {
|
||||
/* No active window pane. */
|
||||
cmdq_error(item, "No active pane to kill.");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
server_kill_pane(wp);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
192
cmd-minimise-pane.c
Normal file
192
cmd-minimise-pane.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* Increase or decrease pane size.
|
||||
*/
|
||||
|
||||
static enum cmd_retval cmd_minimise_pane_minimise_exec(struct cmd *, struct cmdq_item *);
|
||||
static enum cmd_retval cmd_minimise_pane_unminimise_exec(struct cmd *, struct cmdq_item *);
|
||||
|
||||
static enum cmd_retval cmd_minimise_pane_minimise(struct window *, struct window_pane *);
|
||||
static enum cmd_retval cmd_minimise_pane_unminimise(struct window *, struct window_pane *);
|
||||
|
||||
const struct cmd_entry cmd_minimise_pane_entry = {
|
||||
.name = "minimise-pane",
|
||||
.alias = "minimize-pane",
|
||||
|
||||
.args = { "at:", 0, 1, NULL },
|
||||
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
.flags = CMD_AFTERHOOK,
|
||||
.exec = cmd_minimise_pane_minimise_exec
|
||||
};
|
||||
|
||||
const struct cmd_entry cmd_unminimise_pane_entry = {
|
||||
.name = "unminimise-pane",
|
||||
.alias = "unminimize-pane",
|
||||
|
||||
.args = { "at:", 0, 1, NULL },
|
||||
.usage = "[-a] " CMD_TARGET_PANE_USAGE,
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
.flags = CMD_AFTERHOOK,
|
||||
.exec = cmd_minimise_pane_unminimise_exec
|
||||
};
|
||||
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_minimise_pane_minimise_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
__attribute((unused)) struct args *args = cmd_get_args(self);
|
||||
struct cmd_find_state *target = cmdq_get_target(item);
|
||||
struct winlink *wl = target->wl;
|
||||
struct window *w = wl->window;
|
||||
struct window_pane *wp;
|
||||
u_int id;
|
||||
char *cause = NULL;
|
||||
enum cmd_retval rv;
|
||||
|
||||
if (args_has(args, 'a')) {
|
||||
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||
if (!window_pane_visible(wp))
|
||||
continue;
|
||||
rv = cmd_minimise_pane_minimise(w, wp);
|
||||
if (rv != CMD_RETURN_NORMAL)
|
||||
return(rv);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
} else {
|
||||
wp = target->wp;
|
||||
if (wp == NULL) {
|
||||
id = args_strtonum_and_expand(args, 't', 0, INT_MAX, item, &cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(item, "%s target pane", cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
wp = window_pane_find_by_id(id);
|
||||
}
|
||||
if (wp == NULL) {
|
||||
cmdq_error(item, "No target pane to miminise.");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
return(cmd_minimise_pane_minimise(w, wp));
|
||||
}
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_minimise_pane_unminimise_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
__attribute((unused)) struct args *args = cmd_get_args(self);
|
||||
struct cmd_find_state *target = cmdq_get_target(item);
|
||||
struct winlink *wl = target->wl;
|
||||
struct window *w = wl->window;
|
||||
struct window_pane *wp;
|
||||
u_int id;
|
||||
char *cause = NULL;
|
||||
enum cmd_retval rv;
|
||||
|
||||
if (args_has(args, 'a')) {
|
||||
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||
if (!window_pane_visible(wp))
|
||||
continue;
|
||||
rv = cmd_minimise_pane_unminimise(w, wp);
|
||||
if (rv != CMD_RETURN_NORMAL)
|
||||
return(rv);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
} else {
|
||||
wp = target->wp;
|
||||
if (wp == NULL) {
|
||||
id = args_strtonum_and_expand(args, 't', 0, INT_MAX, item, &cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(item, "%s target pane", cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
wp = window_pane_find_by_id(id);
|
||||
}
|
||||
if (wp == NULL) {
|
||||
cmdq_error(item, "No target pane to unmiminise.");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
return(cmd_minimise_pane_unminimise(w, wp));
|
||||
}
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_minimise_pane_minimise(struct window *w, struct window_pane *wp)
|
||||
{
|
||||
struct window_pane *wp2;
|
||||
|
||||
wp->flags |= PANE_MINIMISED;
|
||||
window_deactivate_pane(w, wp, 1);
|
||||
|
||||
/* Fix pane offsets and sizes. */
|
||||
if (w->layout_root != NULL) {
|
||||
wp->saved_layout_cell = wp->layout_cell;
|
||||
layout_minimise_cell(w, wp->layout_cell);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w, NULL);
|
||||
}
|
||||
|
||||
/* Find next visible window in z-index. */
|
||||
TAILQ_FOREACH(wp2, &w->z_index, zentry) {
|
||||
if (!window_pane_visible(wp2))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (wp2 != NULL)
|
||||
window_set_active_pane(w, wp2, 1);
|
||||
|
||||
notify_window("window-layout-changed", w);
|
||||
server_redraw_window(w);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_minimise_pane_unminimise(struct window *w, struct window_pane *wp)
|
||||
{
|
||||
wp->flags &= ~PANE_MINIMISED;
|
||||
|
||||
/* Fix pane offsets and sizes. */
|
||||
if (w->layout_root != NULL && wp->saved_layout_cell != NULL) {
|
||||
wp->layout_cell = wp->saved_layout_cell;
|
||||
wp->saved_layout_cell = NULL;
|
||||
layout_unminimise_cell(w, wp->layout_cell);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w, NULL);
|
||||
}
|
||||
|
||||
window_set_active_pane(w, wp, 1);
|
||||
|
||||
notify_window("window-layout-changed", w);
|
||||
server_redraw_window(w);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
245
cmd-new-pane.c
Normal file
245
cmd-new-pane.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 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 <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
#define NEW_PANE_TEMPLATE "#{session_name}:#{window_index}.#{pane_index}"
|
||||
|
||||
static enum cmd_retval cmd_new_pane_exec(struct cmd *,
|
||||
struct cmdq_item *);
|
||||
|
||||
const struct cmd_entry cmd_new_pane_entry = {
|
||||
.name = "new-pane",
|
||||
.alias = "newp",
|
||||
|
||||
.args = { "bc:de:fF:h:Il:p:Pt:w:x:y:Z", 0, -1, NULL },
|
||||
.usage = "[-bdefhIPvZ] [-c start-directory] [-e environment] "
|
||||
"[-F format] [-l size] " CMD_TARGET_PANE_USAGE
|
||||
" [shell-command [argument ...]]",
|
||||
|
||||
.target = { 't', CMD_FIND_PANE, 0 },
|
||||
|
||||
.flags = 0,
|
||||
.exec = cmd_new_pane_exec
|
||||
};
|
||||
|
||||
|
||||
static enum cmd_retval
|
||||
cmd_new_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
{
|
||||
struct args *args = cmd_get_args(self);
|
||||
struct cmd_find_state *current = cmdq_get_current(item);
|
||||
struct cmd_find_state *target = cmdq_get_target(item);
|
||||
struct spawn_context sc = { 0 };
|
||||
struct client *tc = cmdq_get_target_client(item);
|
||||
struct session *s = target->s;
|
||||
struct winlink *wl = target->wl;
|
||||
struct window *w = wl->window;
|
||||
struct window_pane *wp = target->wp, *new_wp;
|
||||
struct layout_cell *lc;
|
||||
struct cmd_find_state fs;
|
||||
int flags, input;
|
||||
const char *template;
|
||||
char *cause = NULL, *cp;
|
||||
struct args_value *av;
|
||||
u_int count = args_count(args);
|
||||
u_int x, y, sx, sy, pct;
|
||||
static u_int last_x = 0, last_y = 0;
|
||||
|
||||
if (args_has(args, 'f')) {
|
||||
sx = w->sx;
|
||||
sy = w->sy;
|
||||
} else {
|
||||
if (args_has(args, 'l')) {
|
||||
sx = args_percentage_and_expand(args, 'l', 0, INT_MAX, w->sx,
|
||||
item, &cause);
|
||||
sy = args_percentage_and_expand(args, 'l', 0, INT_MAX, w->sy,
|
||||
item, &cause);
|
||||
} else if (args_has(args, 'p')) {
|
||||
pct = args_strtonum_and_expand(args, 'p', 0, 100, item,
|
||||
&cause);
|
||||
if (cause == NULL) {
|
||||
sx = w->sx * pct / 100;
|
||||
sy = w->sy * pct / 100;
|
||||
}
|
||||
} else if (cause == NULL) {
|
||||
sx = w->sx / 2;
|
||||
sy = w->sy / 2;
|
||||
}
|
||||
if (cause != NULL) {
|
||||
cmdq_error(item, "size %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
if (args_has(args, 'w')) {
|
||||
sx = args_strtonum_and_expand(args, 'w', 0, w->sx, item,
|
||||
&cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(item, "size %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
if (args_has(args, 'h')) {
|
||||
sy = args_strtonum_and_expand(args, 'h', 0, w->sy, item,
|
||||
&cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(item, "size %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
if (args_has(args, 'x')) {
|
||||
x = args_strtonum_and_expand(args, 'x', 0, w->sx, item,
|
||||
&cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(item, "size %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
} else {
|
||||
if (last_x == 0) {
|
||||
x = 5;
|
||||
} else {
|
||||
x = (last_x += 5);
|
||||
if (last_x > w->sx)
|
||||
x = 5;
|
||||
}
|
||||
}
|
||||
if (args_has(args, 'y')) {
|
||||
y = args_strtonum_and_expand(args, 'y', 0, w->sx, item,
|
||||
&cause);
|
||||
if (cause != NULL) {
|
||||
cmdq_error(item, "size %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
} else {
|
||||
if (last_y == 0) {
|
||||
y = 5;
|
||||
} else {
|
||||
y = (last_y += 5);
|
||||
if (last_y > w->sy)
|
||||
y = 5;
|
||||
}
|
||||
}
|
||||
|
||||
input = (args_has(args, 'I') && count == 0);
|
||||
|
||||
flags = SPAWN_FLOATING;
|
||||
if (args_has(args, 'b'))
|
||||
flags |= SPAWN_BEFORE;
|
||||
if (args_has(args, 'f'))
|
||||
flags |= SPAWN_FULLSIZE;
|
||||
if (input || (count == 1 && *args_string(args, 0) == '\0'))
|
||||
flags |= SPAWN_EMPTY;
|
||||
|
||||
sc.item = item;
|
||||
sc.s = s;
|
||||
sc.wl = wl;
|
||||
|
||||
sc.wp0 = wp;
|
||||
|
||||
/* Floating panes sit in layout cells which are not in the layout_root
|
||||
* tree so we call it with parent == NULL.
|
||||
*/
|
||||
lc = layout_create_cell(NULL);
|
||||
lc->xoff = x;
|
||||
lc->yoff = y;
|
||||
lc->sx = sx;
|
||||
lc->sy = sy;
|
||||
sc.lc = lc;
|
||||
|
||||
last_x = x; /* Statically save last xoff & yoff so that new */
|
||||
last_y = y; /* floating panes offset so they don't overlap. */
|
||||
|
||||
args_to_vector(args, &sc.argc, &sc.argv);
|
||||
sc.environ = environ_create();
|
||||
|
||||
av = args_first_value(args, 'e');
|
||||
while (av != NULL) {
|
||||
environ_put(sc.environ, av->string, 0);
|
||||
av = args_next_value(av);
|
||||
}
|
||||
|
||||
sc.idx = -1;
|
||||
sc.cwd = args_get(args, 'c');
|
||||
|
||||
sc.flags = flags;
|
||||
if (args_has(args, 'd'))
|
||||
sc.flags |= SPAWN_DETACHED;
|
||||
if (args_has(args, 'Z'))
|
||||
sc.flags |= SPAWN_ZOOM;
|
||||
|
||||
if ((new_wp = spawn_pane(&sc, &cause)) == NULL) {
|
||||
cmdq_error(item, "create pane failed: %s", cause);
|
||||
free(cause);
|
||||
if (sc.argv != NULL)
|
||||
cmd_free_argv(sc.argc, sc.argv);
|
||||
environ_free(sc.environ);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
if (input) {
|
||||
switch (window_pane_start_input(new_wp, item, &cause)) {
|
||||
case -1:
|
||||
server_client_remove_pane(new_wp);
|
||||
window_remove_pane(wp->window, new_wp);
|
||||
cmdq_error(item, "%s", cause);
|
||||
free(cause);
|
||||
if (sc.argv != NULL)
|
||||
cmd_free_argv(sc.argc, sc.argv);
|
||||
environ_free(sc.environ);
|
||||
return (CMD_RETURN_ERROR);
|
||||
case 1:
|
||||
input = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!args_has(args, 'd'))
|
||||
cmd_find_from_winlink_pane(current, wl, new_wp, 0);
|
||||
window_pop_zoom(wp->window);
|
||||
server_redraw_window(wp->window);
|
||||
server_status_session(s);
|
||||
|
||||
if (args_has(args, 'P')) {
|
||||
if ((template = args_get(args, 'F')) == NULL)
|
||||
template = NEW_PANE_TEMPLATE;
|
||||
cp = format_single(item, template, tc, s, wl, new_wp);
|
||||
cmdq_print(item, "%s", cp);
|
||||
free(cp);
|
||||
}
|
||||
|
||||
cmd_find_from_winlink_pane(&fs, wl, new_wp, 0);
|
||||
cmdq_insert_hook(s, item, &fs, "after-split-window");
|
||||
|
||||
if (sc.argv != NULL)
|
||||
cmd_free_argv(sc.argc, sc.argv);
|
||||
environ_free(sc.environ);
|
||||
if (input)
|
||||
return (CMD_RETURN_WAIT);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
@@ -29,7 +29,9 @@
|
||||
|
||||
static enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmdq_item *);
|
||||
|
||||
static void cmd_resize_pane_mouse_update(struct client *,
|
||||
static void cmd_resize_pane_mouse_update_floating(struct client *,
|
||||
struct mouse_event *);
|
||||
static void cmd_resize_pane_mouse_update_tiled(struct client *,
|
||||
struct mouse_event *);
|
||||
|
||||
const struct cmd_entry cmd_resize_pane_entry = {
|
||||
@@ -80,8 +82,15 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
if (c == NULL || c->session != s)
|
||||
return (CMD_RETURN_NORMAL);
|
||||
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update;
|
||||
cmd_resize_pane_mouse_update(c, &event->m);
|
||||
if (c->tty.mouse_wp->flags & PANE_FLOATING) {
|
||||
window_redraw_active_switch(w, c->tty.mouse_wp);
|
||||
window_set_active_pane(w, c->tty.mouse_wp, 1);
|
||||
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_floating;
|
||||
cmd_resize_pane_mouse_update_floating(c, &event->m);
|
||||
} else {
|
||||
c->tty.mouse_drag_update = cmd_resize_pane_mouse_update_tiled;
|
||||
cmd_resize_pane_mouse_update_tiled(c, &event->m);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
@@ -149,7 +158,136 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m)
|
||||
cmd_resize_pane_mouse_update_floating(struct client *c, struct mouse_event *m)
|
||||
{
|
||||
struct winlink *wl;
|
||||
struct window *w;
|
||||
struct window_pane *wp;
|
||||
struct layout_cell *lc;
|
||||
u_int y, ly, x, lx, new_sx, new_sy;
|
||||
int new_xoff, new_yoff, resizes = 0;
|
||||
|
||||
wl = cmd_mouse_window(m, NULL);
|
||||
if (wl == NULL) {
|
||||
c->tty.mouse_drag_update = NULL;
|
||||
return;
|
||||
}
|
||||
w = wl->window;
|
||||
|
||||
y = m->y + m->oy; x = m->x + m->ox;
|
||||
if (m->statusat == 0 && y >= m->statuslines)
|
||||
y -= m->statuslines;
|
||||
else if (m->statusat > 0 && y >= (u_int)m->statusat)
|
||||
y = m->statusat - 1;
|
||||
ly = m->ly + m->oy; lx = m->lx + m->ox;
|
||||
if (m->statusat == 0 && ly >= (u_int)m->statuslines)
|
||||
ly -= m->statuslines;
|
||||
else if (m->statusat > 0 && ly >= (u_int)m->statusat)
|
||||
ly = m->statusat - 1;
|
||||
|
||||
wp = c->tty.mouse_wp;
|
||||
lc = wp->layout_cell;
|
||||
|
||||
log_debug("%s: %%%u resize_pane xoff=%u sx=%u xy=%ux%u lxy=%ux%u",
|
||||
__func__, wp->id, wp->xoff, wp->sx, x, y, lx, ly);
|
||||
if ((((int)lx == wp->xoff - 1) || ((int)lx == wp->xoff)) &&
|
||||
((int)ly == wp->yoff - 1)) {
|
||||
/* Top left corner */
|
||||
new_sx = lc->sx + (lx - x);
|
||||
if (new_sx < PANE_MINIMUM)
|
||||
new_sx = PANE_MINIMUM;
|
||||
new_sy = lc->sy + (ly - y);
|
||||
if (new_sy < PANE_MINIMUM)
|
||||
new_sy = PANE_MINIMUM;
|
||||
new_xoff = x + 1; /* Because mouse is on border at xoff - 1 */
|
||||
new_yoff = y + 1;
|
||||
layout_set_size(lc, new_sx, new_sy, new_xoff, new_yoff);
|
||||
resizes++;
|
||||
} else if ((((int)lx == wp->xoff + (int)wp->sx + 1) ||
|
||||
((int)lx == wp->xoff + (int)wp->sx)) &&
|
||||
((int)ly == wp->yoff - 1)) {
|
||||
/* Top right corner */
|
||||
new_sx = x - lc->xoff;
|
||||
if (new_sx < PANE_MINIMUM)
|
||||
new_sx = PANE_MINIMUM;
|
||||
new_sy = lc->sy + (ly - y);
|
||||
if (new_sy < PANE_MINIMUM)
|
||||
new_sy = PANE_MINIMUM;
|
||||
new_yoff = y + 1;
|
||||
layout_set_size(lc, new_sx, new_sy, lc->xoff, new_yoff);
|
||||
resizes++;
|
||||
} else if ((((int)lx == wp->xoff - 1) || ((int)lx == wp->xoff)) &&
|
||||
((int)ly == wp->yoff + (int)wp->sy)) {
|
||||
/* Bottom left corner */
|
||||
new_sx = lc->sx + (lx - x);
|
||||
if (new_sx < PANE_MINIMUM)
|
||||
new_sx = PANE_MINIMUM;
|
||||
new_sy = y - lc->yoff;
|
||||
if (new_sy < PANE_MINIMUM)
|
||||
return;
|
||||
new_xoff = x + 1;
|
||||
layout_set_size(lc, new_sx, new_sy, new_xoff, lc->yoff);
|
||||
resizes++;
|
||||
} else if ((((int)lx == wp->xoff + (int)wp->sx + 1) ||
|
||||
((int)lx == wp->xoff + (int)wp->sx)) &&
|
||||
((int)ly == wp->yoff + (int)wp->sy)) {
|
||||
/* Bottom right corner */
|
||||
new_sx = x - lc->xoff;
|
||||
if (new_sx < PANE_MINIMUM)
|
||||
new_sx = PANE_MINIMUM;
|
||||
new_sy = y - lc->yoff;
|
||||
if (new_sy < PANE_MINIMUM)
|
||||
new_sy = PANE_MINIMUM;
|
||||
layout_set_size(lc, new_sx, new_sy, lc->xoff, lc->yoff);
|
||||
resizes++;
|
||||
} else if ((int)lx == wp->xoff + (int)wp->sx + 1) {
|
||||
/* Right border */
|
||||
new_sx = x - lc->xoff;
|
||||
if (new_sx < PANE_MINIMUM)
|
||||
return;
|
||||
layout_set_size(lc, new_sx, lc->sy, lc->xoff, lc->yoff);
|
||||
resizes++;
|
||||
} else if ((int)lx == wp->xoff - 1) {
|
||||
/* Left border */
|
||||
new_sx = lc->sx + (lx - x);
|
||||
if (new_sx < PANE_MINIMUM)
|
||||
return;
|
||||
new_xoff = x + 1;
|
||||
layout_set_size(lc, new_sx, lc->sy, new_xoff, lc->yoff);
|
||||
resizes++;
|
||||
} else if ((int)ly == wp->yoff + (int)wp->sy) {
|
||||
/* Bottom border */
|
||||
new_sy = y - lc->yoff;
|
||||
if (new_sy < PANE_MINIMUM)
|
||||
return;
|
||||
layout_set_size(lc, lc->sx, new_sy, lc->xoff, lc->yoff);
|
||||
resizes++;
|
||||
} else if ((int)ly == wp->yoff - 1) {
|
||||
/* Top border (move instead of resize) */
|
||||
new_xoff = lc->xoff + (x - lx);
|
||||
new_yoff = y + 1;
|
||||
layout_set_size(lc, lc->sx, lc->sy, new_xoff, new_yoff);
|
||||
/* To resize instead of move:
|
||||
new_sy = wp->sy + (ly - y);
|
||||
if (new_sy < PANE_MINIMUM)
|
||||
return;
|
||||
new_yoff = y + 1;
|
||||
layout_set_size(lc, lc->sx, new_sy, lc->xoff, new_yoff);
|
||||
*/
|
||||
resizes++;
|
||||
} else {
|
||||
log_debug("%s: %%%u resize_pane xoff=%u sx=%u xy=%ux%u lxy=%ux%u <else>",
|
||||
__func__, wp->id, wp->xoff, wp->sx, x, y, lx, ly);
|
||||
}
|
||||
if (resizes != 0) {
|
||||
layout_fix_panes(w, NULL);
|
||||
server_redraw_window(w);
|
||||
server_redraw_window_borders(w);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_resize_pane_mouse_update_tiled(struct client *c, struct mouse_event *m)
|
||||
{
|
||||
struct winlink *wl;
|
||||
struct window *w;
|
||||
|
||||
@@ -90,7 +90,7 @@ cmd_select_layout_exec(struct cmd *self, struct cmdq_item *item)
|
||||
previous = 1;
|
||||
|
||||
oldlayout = w->old_layout;
|
||||
w->old_layout = layout_dump(w->layout_root);
|
||||
w->old_layout = layout_dump(w, w->layout_root);
|
||||
|
||||
if (next || previous) {
|
||||
if (next)
|
||||
|
||||
@@ -160,6 +160,10 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
server_redraw_window_borders(markedwp->window);
|
||||
server_status_window(markedwp->window);
|
||||
}
|
||||
if (wp->flags & PANE_FLOATING) {
|
||||
window_redraw_active_switch(w, wp);
|
||||
window_set_active_pane(w, wp, 1);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,11 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
struct args_value *av;
|
||||
u_int count = args_count(args), curval = 0;
|
||||
|
||||
if (wp->flags & PANE_FLOATING) {
|
||||
cmdq_error(item, "can't split a floating pane");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
||||
type = LAYOUT_TOPBOTTOM;
|
||||
if (args_has(args, 'h'))
|
||||
type = LAYOUT_LEFTRIGHT;
|
||||
|
||||
10
cmd.c
10
cmd.c
@@ -69,8 +69,10 @@ extern const struct cmd_entry cmd_load_buffer_entry;
|
||||
extern const struct cmd_entry cmd_lock_client_entry;
|
||||
extern const struct cmd_entry cmd_lock_server_entry;
|
||||
extern const struct cmd_entry cmd_lock_session_entry;
|
||||
extern const struct cmd_entry cmd_minimise_pane_entry;
|
||||
extern const struct cmd_entry cmd_move_pane_entry;
|
||||
extern const struct cmd_entry cmd_move_window_entry;
|
||||
extern const struct cmd_entry cmd_new_pane_entry;
|
||||
extern const struct cmd_entry cmd_new_session_entry;
|
||||
extern const struct cmd_entry cmd_new_window_entry;
|
||||
extern const struct cmd_entry cmd_next_layout_entry;
|
||||
@@ -116,6 +118,7 @@ extern const struct cmd_entry cmd_swap_window_entry;
|
||||
extern const struct cmd_entry cmd_switch_client_entry;
|
||||
extern const struct cmd_entry cmd_unbind_key_entry;
|
||||
extern const struct cmd_entry cmd_unlink_window_entry;
|
||||
extern const struct cmd_entry cmd_unminimise_pane_entry;
|
||||
extern const struct cmd_entry cmd_wait_for_entry;
|
||||
|
||||
const struct cmd_entry *cmd_table[] = {
|
||||
@@ -161,8 +164,10 @@ const struct cmd_entry *cmd_table[] = {
|
||||
&cmd_lock_client_entry,
|
||||
&cmd_lock_server_entry,
|
||||
&cmd_lock_session_entry,
|
||||
&cmd_minimise_pane_entry,
|
||||
&cmd_move_pane_entry,
|
||||
&cmd_move_window_entry,
|
||||
&cmd_new_pane_entry,
|
||||
&cmd_new_session_entry,
|
||||
&cmd_new_window_entry,
|
||||
&cmd_next_layout_entry,
|
||||
@@ -208,6 +213,7 @@ const struct cmd_entry *cmd_table[] = {
|
||||
&cmd_switch_client_entry,
|
||||
&cmd_unbind_key_entry,
|
||||
&cmd_unlink_window_entry,
|
||||
&cmd_unminimise_pane_entry,
|
||||
&cmd_wait_for_entry,
|
||||
NULL
|
||||
};
|
||||
@@ -772,9 +778,9 @@ cmd_mouse_at(struct window_pane *wp, struct mouse_event *m, u_int *xp,
|
||||
if (m->statusat == 0 && y >= m->statuslines)
|
||||
y -= m->statuslines;
|
||||
|
||||
if (x < wp->xoff || x >= wp->xoff + wp->sx)
|
||||
if ((int)x < wp->xoff || (int)x >= wp->xoff + (int)wp->sx)
|
||||
return (-1);
|
||||
if (y < wp->yoff || y >= wp->yoff + wp->sy)
|
||||
if ((int)y < wp->yoff || (int)y >= wp->yoff + (int)wp->sy)
|
||||
return (-1);
|
||||
|
||||
if (xp != NULL)
|
||||
|
||||
27
configure.ac
27
configure.ac
@@ -462,33 +462,14 @@ if test "x$enable_cgroups" = xyes; then
|
||||
fi
|
||||
|
||||
# Enable sixel support.
|
||||
AC_ARG_ENABLE(
|
||||
sixel-images,
|
||||
AS_HELP_STRING(--enable-sixel-images, enable sixel images)
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
sixel,
|
||||
AS_HELP_STRING(--enable-sixel support),
|
||||
[
|
||||
enable_sixel_images="$enableval"
|
||||
]
|
||||
AS_HELP_STRING(--enable-sixel, enable sixel images)
|
||||
)
|
||||
|
||||
if test "x$enable_sixel_images" = xyes; then
|
||||
AC_DEFINE(ENABLE_SIXEL_IMAGES)
|
||||
if test "x$enable_sixel" = xyes; then
|
||||
AC_DEFINE(ENABLE_SIXEL)
|
||||
fi
|
||||
AM_CONDITIONAL(ENABLE_SIXEL_IMAGES, [test "x$enable_sixel_images" = xyes])
|
||||
|
||||
# Enable kitty graphics protocol support.
|
||||
AC_ARG_ENABLE(
|
||||
kitty-images,
|
||||
AS_HELP_STRING(--enable-kitty-images, enable kitty terminal graphics)
|
||||
)
|
||||
if test "x$enable_kitty_images" = xyes; then
|
||||
AC_DEFINE(ENABLE_KITTY_IMAGES)
|
||||
fi
|
||||
AM_CONDITIONAL(ENABLE_KITTY_IMAGES, [test "x$enable_kitty_images" = xyes])
|
||||
AM_CONDITIONAL(ENABLE_SIXEL, [test "x$enable_sixel" = xyes])
|
||||
|
||||
# Check for b64_ntop. If we have b64_ntop, we assume b64_pton as well.
|
||||
AC_MSG_CHECKING(for b64_ntop)
|
||||
|
||||
41
format.c
41
format.c
@@ -825,8 +825,8 @@ format_cb_window_layout(struct format_tree *ft)
|
||||
return (NULL);
|
||||
|
||||
if (w->saved_layout_root != NULL)
|
||||
return (layout_dump(w->saved_layout_root));
|
||||
return (layout_dump(w->layout_root));
|
||||
return (layout_dump(w, w->saved_layout_root));
|
||||
return (layout_dump(w, w->layout_root));
|
||||
}
|
||||
|
||||
/* Callback for window_visible_layout. */
|
||||
@@ -838,7 +838,7 @@ format_cb_window_visible_layout(struct format_tree *ft)
|
||||
if (w == NULL)
|
||||
return (NULL);
|
||||
|
||||
return (layout_dump(w->layout_root));
|
||||
return (layout_dump(w, w->layout_root));
|
||||
}
|
||||
|
||||
/* Callback for pane_start_command. */
|
||||
@@ -1004,6 +1004,20 @@ format_cb_pane_fg(struct format_tree *ft)
|
||||
return (xstrdup(colour_tostring(gc.fg)));
|
||||
}
|
||||
|
||||
/* Callback for pane_floating_flag. */
|
||||
static void *
|
||||
format_cb_pane_floating_flag(struct format_tree *ft)
|
||||
{
|
||||
struct window_pane *wp = ft->wp;
|
||||
|
||||
if (wp != NULL) {
|
||||
if (wp->flags & PANE_FLOATING)
|
||||
return (xstrdup("1"));
|
||||
return (xstrdup("0"));
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Callback for pane_bg. */
|
||||
static void *
|
||||
format_cb_pane_bg(struct format_tree *ft)
|
||||
@@ -2562,16 +2576,12 @@ format_cb_version(__unused struct format_tree *ft)
|
||||
|
||||
/* Callback for sixel_support. */
|
||||
static void *
|
||||
format_cb_image_support(__unused struct format_tree *ft)
|
||||
format_cb_sixel_support(__unused struct format_tree *ft)
|
||||
{
|
||||
#if defined(ENABLE_SIXEL_IMAGES) && defined(ENABLE_KITTY_IMAGES)
|
||||
return (xstrdup("kitty,sixel"));
|
||||
#elif defined(ENABLE_SIXEL_IMAGES)
|
||||
return (xstrdup("sixel"));
|
||||
#elif defined(ENABLE_KITTY_IMAGES)
|
||||
return (xstrdup("kitty"));
|
||||
#ifdef ENABLE_SIXEL
|
||||
return (xstrdup("1"));
|
||||
#else
|
||||
return (NULL);
|
||||
return (xstrdup("0"));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -3194,9 +3204,6 @@ static const struct format_table_entry format_table[] = {
|
||||
{ "host_short", FORMAT_TABLE_STRING,
|
||||
format_cb_host_short
|
||||
},
|
||||
{ "image_support", FORMAT_TABLE_STRING,
|
||||
format_cb_image_support
|
||||
},
|
||||
{ "insert_flag", FORMAT_TABLE_STRING,
|
||||
format_cb_insert_flag
|
||||
},
|
||||
@@ -3302,6 +3309,9 @@ static const struct format_table_entry format_table[] = {
|
||||
{ "pane_fg", FORMAT_TABLE_STRING,
|
||||
format_cb_pane_fg
|
||||
},
|
||||
{ "pane_floating_flag", FORMAT_TABLE_STRING,
|
||||
format_cb_pane_floating_flag
|
||||
},
|
||||
{ "pane_format", FORMAT_TABLE_STRING,
|
||||
format_cb_pane_format
|
||||
},
|
||||
@@ -3473,6 +3483,9 @@ static const struct format_table_entry format_table[] = {
|
||||
{ "session_windows", FORMAT_TABLE_STRING,
|
||||
format_cb_session_windows
|
||||
},
|
||||
{ "sixel_support", FORMAT_TABLE_STRING,
|
||||
format_cb_sixel_support
|
||||
},
|
||||
{ "socket_path", FORMAT_TABLE_STRING,
|
||||
format_cb_socket_path
|
||||
},
|
||||
|
||||
11
grid.c
11
grid.c
@@ -495,7 +495,7 @@ static void
|
||||
grid_expand_line(struct grid *gd, u_int py, u_int sx, u_int bg)
|
||||
{
|
||||
struct grid_line *gl;
|
||||
u_int xx, old_cellsize;
|
||||
u_int xx;
|
||||
|
||||
gl = &gd->linedata[py];
|
||||
if (sx <= gl->cellsize)
|
||||
@@ -508,10 +508,13 @@ grid_expand_line(struct grid *gd, u_int py, u_int sx, u_int bg)
|
||||
else if (gd->sx > sx)
|
||||
sx = gd->sx;
|
||||
|
||||
old_cellsize = gl->cellsize;
|
||||
gl->celldata = xrecallocarray(gl->celldata, old_cellsize, sx,
|
||||
gl->celldata = xreallocarray(gl->celldata, sx,
|
||||
sizeof *gl->celldata);
|
||||
for (xx = old_cellsize; xx < sx; xx++)
|
||||
if (gl->cellsize < sx) {
|
||||
memset(gl->celldata + gl->cellsize, 0,
|
||||
(sx - gl->cellsize) * sizeof *gl->celldata);
|
||||
}
|
||||
for (xx = gl->cellsize; xx < sx; xx++)
|
||||
grid_clear_cell(gd, xx, py, bg);
|
||||
gl->cellsize = sx;
|
||||
}
|
||||
|
||||
325
image-kitty.c
325
image-kitty.c
@@ -1,325 +0,0 @@
|
||||
/* $OpenBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2026 Thomas Adam <thomas@xteddy.org>
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
* kitty_image stores the raw decoded pixel data and metadata from a kitty
|
||||
* graphics protocol APC sequence. It is used to re-emit the sequence to the
|
||||
* outer terminal on redraw.
|
||||
*/
|
||||
struct kitty_image {
|
||||
/* Control-data fields parsed from the APC sequence. */
|
||||
char action; /* a=: 'T'=transmit+display, 't', 'p', 'd' */
|
||||
u_int format; /* f=: 32=RGBA, 24=RGB, 100=PNG */
|
||||
char medium; /* t=: 'd'=direct, 'f'=file, 't'=tmp, 's'=shm */
|
||||
u_int pixel_w; /* s=: source image pixel width */
|
||||
u_int pixel_h; /* v=: source image pixel height */
|
||||
u_int cols; /* c=: display columns (0=auto) */
|
||||
u_int rows; /* r=: display rows (0=auto) */
|
||||
u_int image_id; /* i=: image id (0=unassigned) */
|
||||
u_int image_num; /* I=: image number */
|
||||
u_int placement_id; /* p=: placement id */
|
||||
u_int more; /* m=: 1=more chunks coming, 0=last */
|
||||
u_int quiet; /* q=: suppress responses */
|
||||
int z_index; /* z=: z-index */
|
||||
char compression; /* o=: 'z'=zlib, 0=none */
|
||||
char delete_what; /* d=: delete target (used with a=d) */
|
||||
|
||||
/* Cell size at the time of parsing (from the owning window). */
|
||||
u_int xpixel;
|
||||
u_int ypixel;
|
||||
|
||||
/* Original base64-encoded payload (concatenated across all chunks). */
|
||||
char *encoded;
|
||||
size_t encodedlen;
|
||||
|
||||
char *ctrl;
|
||||
size_t ctrllen;
|
||||
};
|
||||
|
||||
/*
|
||||
* Parse control-data key=value pairs from a kitty APC sequence.
|
||||
* Format: key=value,key=value,...
|
||||
*/
|
||||
static int
|
||||
kitty_parse_control(const char *ctrl, size_t ctrllen, struct kitty_image *ki)
|
||||
{
|
||||
const char *p = ctrl, *end = ctrl + ctrllen, *errstr;
|
||||
char key[4], val[32];
|
||||
size_t klen, vlen;
|
||||
|
||||
while (p < end) {
|
||||
klen = 0;
|
||||
while (p < end && *p != '=' && klen < sizeof(key) - 1)
|
||||
key[klen++] = *p++;
|
||||
key[klen] = '\0';
|
||||
if (p >= end || *p != '=')
|
||||
return (-1);
|
||||
p++;
|
||||
|
||||
vlen = 0;
|
||||
while (p < end && *p != ',' && vlen < sizeof(val) - 1)
|
||||
val[vlen++] = *p++;
|
||||
val[vlen] = '\0';
|
||||
if (p < end && *p == ',')
|
||||
p++;
|
||||
|
||||
if (klen != 1)
|
||||
continue;
|
||||
|
||||
switch (key[0]) {
|
||||
case 'a':
|
||||
ki->action = val[0];
|
||||
break;
|
||||
case 'f':
|
||||
ki->format = strtonum(val, 0, UINT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
break;
|
||||
case 't':
|
||||
ki->medium = val[0];
|
||||
break;
|
||||
case 's':
|
||||
ki->pixel_w = strtonum(val, 0, UINT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
break;
|
||||
case 'v':
|
||||
ki->pixel_h = strtonum(val, 0, UINT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
break;
|
||||
case 'c':
|
||||
ki->cols = strtonum(val, 0, UINT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
break;
|
||||
case 'r':
|
||||
ki->rows = strtonum(val, 0, UINT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
break;
|
||||
case 'i':
|
||||
ki->image_id = strtonum(val, 0, UINT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
break;
|
||||
case 'I':
|
||||
ki->image_num = strtonum(val, 0, UINT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
break;
|
||||
case 'p':
|
||||
ki->placement_id = strtonum(val, 0, UINT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
break;
|
||||
case 'm':
|
||||
ki->more = strtonum(val, 0, UINT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
break;
|
||||
case 'q':
|
||||
ki->quiet = strtonum(val, 0, UINT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
break;
|
||||
case 'z':
|
||||
ki->z_index = strtonum(val, INT_MIN, INT_MAX, &errstr);
|
||||
if (errstr != NULL)
|
||||
return (-1);
|
||||
break;
|
||||
case 'o':
|
||||
ki->compression = val[0];
|
||||
break;
|
||||
case 'd':
|
||||
ki->delete_what = val[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a kitty APC body (after the leading 'G').
|
||||
* Stores the original control string and base64 payload verbatim for
|
||||
* pass-through re-emission to the outer terminal.
|
||||
*/
|
||||
struct kitty_image *
|
||||
kitty_parse(const u_char *buf, size_t len, u_int xpixel, u_int ypixel)
|
||||
{
|
||||
struct kitty_image *ki;
|
||||
const u_char *semi;
|
||||
const char *ctrl;
|
||||
size_t ctrllen, paylen;
|
||||
|
||||
if (len == 0)
|
||||
return (NULL);
|
||||
|
||||
semi = memchr(buf, ';', len);
|
||||
if (semi != NULL) {
|
||||
ctrl = (const char *)buf;
|
||||
ctrllen = semi - buf;
|
||||
paylen = len - ctrllen - 1;
|
||||
} else {
|
||||
ctrl = (const char *)buf;
|
||||
ctrllen = len;
|
||||
paylen = 0;
|
||||
}
|
||||
|
||||
ki = xcalloc(1, sizeof *ki);
|
||||
ki->xpixel = xpixel;
|
||||
ki->ypixel = ypixel;
|
||||
ki->action = 'T';
|
||||
ki->format = 32;
|
||||
ki->medium = 'd';
|
||||
|
||||
if (kitty_parse_control(ctrl, ctrllen, ki) != 0) {
|
||||
free(ki);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (paylen > 0) {
|
||||
ki->encoded = xmalloc(paylen + 1);
|
||||
memcpy(ki->encoded, semi + 1, paylen);
|
||||
ki->encoded[paylen] = '\0';
|
||||
ki->encodedlen = paylen;
|
||||
}
|
||||
|
||||
ki->ctrl = xmalloc(ctrllen + 1);
|
||||
memcpy(ki->ctrl, ctrl, ctrllen);
|
||||
ki->ctrl[ctrllen] = '\0';
|
||||
ki->ctrllen = ctrllen;
|
||||
|
||||
return (ki);
|
||||
}
|
||||
|
||||
void
|
||||
kitty_free(struct kitty_image *ki)
|
||||
{
|
||||
if (ki == NULL)
|
||||
return;
|
||||
free(ki->encoded);
|
||||
free(ki->ctrl);
|
||||
free(ki);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the size in cells of a kitty image. If cols/rows are 0 (auto),
|
||||
* calculate from pixel dimensions. Returns size via sx/sy pointers.
|
||||
*/
|
||||
void
|
||||
kitty_size_in_cells(struct kitty_image *ki, u_int *sx, u_int *sy)
|
||||
{
|
||||
*sx = ki->cols;
|
||||
*sy = ki->rows;
|
||||
|
||||
/*
|
||||
* If cols/rows are 0, they mean "auto" - calculate from
|
||||
* pixel dimensions.
|
||||
*/
|
||||
if (*sx == 0 && ki->pixel_w > 0 && ki->xpixel > 0) {
|
||||
*sx = (ki->pixel_w + ki->xpixel - 1) / ki->xpixel;
|
||||
}
|
||||
if (*sy == 0 && ki->pixel_h > 0 && ki->ypixel > 0) {
|
||||
*sy = (ki->pixel_h + ki->ypixel - 1) / ki->ypixel;
|
||||
}
|
||||
|
||||
/* If still 0, use a reasonable default */
|
||||
if (*sx == 0)
|
||||
*sx = 10;
|
||||
if (*sy == 0)
|
||||
*sy = 10;
|
||||
}
|
||||
|
||||
char
|
||||
kitty_get_action(struct kitty_image *ki)
|
||||
{
|
||||
return (ki->action);
|
||||
}
|
||||
|
||||
u_int
|
||||
kitty_get_image_id(struct kitty_image *ki)
|
||||
{
|
||||
return (ki->image_id);
|
||||
}
|
||||
|
||||
u_int
|
||||
kitty_get_rows(struct kitty_image *ki)
|
||||
{
|
||||
return (ki->rows);
|
||||
}
|
||||
|
||||
/*
|
||||
* Serialize a kitty_image back into an APC escape sequence for transmission
|
||||
* to the terminal. This recreates the original command that was parsed.
|
||||
*/
|
||||
char *
|
||||
kitty_print(struct kitty_image *ki, size_t *outlen)
|
||||
{
|
||||
char *out;
|
||||
size_t total, pos;
|
||||
|
||||
if (ki == NULL || ki->ctrl == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* Calculate total length: ESC _ G + ctrl + ; + encoded + ESC \ */
|
||||
total = 3 + ki->ctrllen; /* \033_G + ctrl */
|
||||
if (ki->encoded != NULL && ki->encodedlen > 0) {
|
||||
total += 1 + ki->encodedlen; /* ; + encoded */
|
||||
}
|
||||
total += 2; /* \033\\ */
|
||||
|
||||
out = xmalloc(total + 1);
|
||||
*outlen = total;
|
||||
|
||||
/* Build the sequence */
|
||||
pos = 0;
|
||||
memcpy(out + pos, "\033_G", 3);
|
||||
pos += 3;
|
||||
memcpy(out + pos, ki->ctrl, ki->ctrllen);
|
||||
pos += ki->ctrllen;
|
||||
|
||||
if (ki->encoded != NULL && ki->encodedlen > 0) {
|
||||
out[pos++] = ';';
|
||||
memcpy(out + pos, ki->encoded, ki->encodedlen);
|
||||
pos += ki->encodedlen;
|
||||
}
|
||||
|
||||
memcpy(out + pos, "\033\\", 2);
|
||||
pos += 2;
|
||||
out[pos] = '\0';
|
||||
|
||||
return (out);
|
||||
}
|
||||
|
||||
char *
|
||||
kitty_delete_all(size_t *outlen)
|
||||
{
|
||||
char *out;
|
||||
|
||||
out = xstrdup("\033_Ga=d,d=a\033\\");
|
||||
*outlen = strlen(out);
|
||||
return (out);
|
||||
}
|
||||
112
image.c
112
image.c
@@ -61,22 +61,7 @@ image_free(struct image *im)
|
||||
all_images_count--;
|
||||
|
||||
TAILQ_REMOVE(&s->images, im, entry);
|
||||
|
||||
switch (im->type) {
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
case IMAGE_SIXEL:
|
||||
sixel_free(im->data.sixel);
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
case IMAGE_KITTY:
|
||||
kitty_free(im->data.kitty);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
sixel_free(im->data);
|
||||
free(im->fallback);
|
||||
free(im);
|
||||
}
|
||||
@@ -96,30 +81,13 @@ image_free_all(struct screen *s)
|
||||
|
||||
/* Create text placeholder for an image. */
|
||||
static void
|
||||
image_fallback(char **ret, enum image_type type, u_int sx, u_int sy)
|
||||
image_fallback(char **ret, u_int sx, u_int sy)
|
||||
{
|
||||
char *buf, *label;
|
||||
u_int py, size, lsize;
|
||||
const char *type_name;
|
||||
|
||||
switch (type) {
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
case IMAGE_SIXEL:
|
||||
type_name = "SIXEL";
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
case IMAGE_KITTY:
|
||||
type_name = "KITTY";
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
type_name = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
/* Allocate first line. */
|
||||
lsize = xasprintf(&label, "%s IMAGE (%ux%u)\r\n", type_name, sx, sy) + 1;
|
||||
lsize = xasprintf(&label, "SIXEL IMAGE (%ux%u)\r\n", sx, sy) + 1;
|
||||
if (sx < lsize - 3)
|
||||
size = lsize - 1;
|
||||
else
|
||||
@@ -154,36 +122,19 @@ image_fallback(char **ret, enum image_type type, u_int sx, u_int sy)
|
||||
}
|
||||
|
||||
struct image*
|
||||
image_store(struct screen *s, enum image_type type, void *data)
|
||||
image_store(struct screen *s, struct sixel_image *si)
|
||||
{
|
||||
struct image *im;
|
||||
|
||||
im = xcalloc(1, sizeof *im);
|
||||
|
||||
im->type = type;
|
||||
im->s = s;
|
||||
im->data = si;
|
||||
|
||||
im->px = s->cx;
|
||||
im->py = s->cy;
|
||||
sixel_size_in_cells(si, &im->sx, &im->sy);
|
||||
|
||||
switch (type) {
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
case IMAGE_SIXEL:
|
||||
im->data.sixel = data;
|
||||
sixel_size_in_cells(im->data.sixel, &im->sx, &im->sy);
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
case IMAGE_KITTY:
|
||||
im->data.kitty = data;
|
||||
kitty_size_in_cells(im->data.kitty, &im->sx, &im->sy);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
image_fallback(&im->fallback, type, im->sx, im->sy);
|
||||
image_fallback(&im->fallback, im->sx, im->sy);
|
||||
|
||||
image_log(im, __func__, NULL);
|
||||
TAILQ_INSERT_TAIL(&s->images, im, entry);
|
||||
@@ -237,10 +188,8 @@ image_scroll_up(struct screen *s, u_int lines)
|
||||
{
|
||||
struct image *im, *im1;
|
||||
int redraw = 0;
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
struct sixel_image *new;
|
||||
u_int sx, sy;
|
||||
#endif
|
||||
struct sixel_image *new;
|
||||
|
||||
TAILQ_FOREACH_SAFE(im, &s->images, entry, im1) {
|
||||
if (im->py >= lines) {
|
||||
@@ -255,43 +204,20 @@ image_scroll_up(struct screen *s, u_int lines)
|
||||
redraw = 1;
|
||||
continue;
|
||||
}
|
||||
sx = im->sx;
|
||||
sy = (im->py + im->sy) - lines;
|
||||
image_log(im, __func__, "3, lines=%u, sy=%u", lines, sy);
|
||||
|
||||
/* Image is partially scrolled off - need to crop it */
|
||||
switch (im->type) {
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
case IMAGE_SIXEL:
|
||||
sx = im->sx;
|
||||
sy = (im->py + im->sy) - lines;
|
||||
image_log(im, __func__, "sixel, lines=%u, sy=%u",
|
||||
lines, sy);
|
||||
new = sixel_scale(im->data, 0, 0, 0, im->sy - sy, sx, sy, 1);
|
||||
sixel_free(im->data);
|
||||
im->data = new;
|
||||
|
||||
new = sixel_scale(im->data.sixel, 0, 0, 0, im->sy - sy,
|
||||
sx, sy, 1);
|
||||
sixel_free(im->data.sixel);
|
||||
im->data.sixel = new;
|
||||
im->py = 0;
|
||||
sixel_size_in_cells(im->data, &im->sx, &im->sy);
|
||||
|
||||
im->py = 0;
|
||||
sixel_size_in_cells(im->data.sixel, &im->sx, &im->sy);
|
||||
|
||||
free(im->fallback);
|
||||
image_fallback(&im->fallback, im->type, im->sx, im->sy);
|
||||
redraw = 1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
case IMAGE_KITTY:
|
||||
/*
|
||||
* For kitty images, we can't rescale - the terminal
|
||||
* owns the placement. Just adjust position and let
|
||||
* the terminal handle clipping.
|
||||
*/
|
||||
im->py = 0;
|
||||
redraw = 1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
free(im->fallback);
|
||||
image_fallback(&im->fallback, im->sx, im->sy);
|
||||
redraw = 1;
|
||||
}
|
||||
return (redraw);
|
||||
}
|
||||
|
||||
101
input.c
101
input.c
@@ -145,7 +145,6 @@ struct input_ctx {
|
||||
*/
|
||||
struct evbuffer *since_ground;
|
||||
struct event ground_timer;
|
||||
|
||||
};
|
||||
|
||||
/* Helper functions. */
|
||||
@@ -181,7 +180,6 @@ static void input_ground(struct input_ctx *);
|
||||
static void input_enter_dcs(struct input_ctx *);
|
||||
static void input_enter_osc(struct input_ctx *);
|
||||
static void input_exit_osc(struct input_ctx *);
|
||||
static int input_da1_has_sixel(struct input_ctx *);
|
||||
static void input_enter_apc(struct input_ctx *);
|
||||
static void input_exit_apc(struct input_ctx *);
|
||||
static void input_enter_rename(struct input_ctx *);
|
||||
@@ -1383,10 +1381,6 @@ input_esc_dispatch(struct input_ctx *ictx)
|
||||
input_reset_cell(ictx);
|
||||
screen_write_reset(sctx);
|
||||
screen_write_fullredraw(sctx);
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
if (ictx->wp != NULL)
|
||||
tty_kitty_delete_all_pane(ictx->wp);
|
||||
#endif
|
||||
break;
|
||||
case INPUT_ESC_IND:
|
||||
screen_write_linefeed(sctx, 0, ictx->cell.cell.bg);
|
||||
@@ -1562,10 +1556,11 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
case -1:
|
||||
break;
|
||||
case 0:
|
||||
if (input_da1_has_sixel(ictx))
|
||||
input_reply(ictx, 1, "\033[?1;2;4c");
|
||||
else
|
||||
input_reply(ictx, 1, "\033[?1;2c");
|
||||
#ifdef ENABLE_SIXEL
|
||||
input_reply(ictx, 1, "\033[?1;2;4c");
|
||||
#else
|
||||
input_reply(ictx, 1, "\033[?1;2c");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||
@@ -2035,7 +2030,7 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
|
||||
static void
|
||||
input_csi_dispatch_sm_graphics(__unused struct input_ctx *ictx)
|
||||
{
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
int n, m, o;
|
||||
|
||||
if (ictx->param_list_len > 3)
|
||||
@@ -2560,7 +2555,7 @@ input_dcs_dispatch(struct input_ctx *ictx)
|
||||
const char prefix[] = "tmux;";
|
||||
const u_int prefixlen = (sizeof prefix) - 1;
|
||||
long long allow_passthrough = 0;
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
struct window *w;
|
||||
struct sixel_image *si;
|
||||
int p2;
|
||||
@@ -2575,7 +2570,7 @@ input_dcs_dispatch(struct input_ctx *ictx)
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
w = wp->window;
|
||||
if (buf[0] == 'q' && ictx->interm_len == 0) {
|
||||
if (input_split(ictx) != 0)
|
||||
@@ -2721,79 +2716,6 @@ input_enter_apc(struct input_ctx *ictx)
|
||||
ictx->flags &= ~INPUT_LAST;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if any client viewing this pane has an outer terminal that supports
|
||||
* sixel, so we can report it in the DA1 response.
|
||||
*/
|
||||
static int
|
||||
input_da1_has_sixel(__unused struct input_ctx *ictx)
|
||||
{
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
struct window_pane *wp = ictx->wp;
|
||||
struct client *c;
|
||||
|
||||
if (wp == NULL)
|
||||
return (0);
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session == NULL)
|
||||
continue;
|
||||
if (c->session->curw->window != wp->window)
|
||||
continue;
|
||||
if (c->tty.term->flags & TERM_SIXEL)
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
/* Handle a kitty graphics APC sequence. */
|
||||
static void
|
||||
input_apc_kitty_image(struct input_ctx *ictx)
|
||||
{
|
||||
struct screen_write_ctx *sctx = &ictx->ctx;
|
||||
struct window_pane *wp = ictx->wp;
|
||||
struct window *w;
|
||||
struct kitty_image *ki;
|
||||
|
||||
if (wp == NULL)
|
||||
return;
|
||||
|
||||
w = wp->window;
|
||||
ki = kitty_parse(ictx->input_buf + 1, ictx->input_len - 1,
|
||||
w->xpixel, w->ypixel);
|
||||
if (ki == NULL)
|
||||
return;
|
||||
|
||||
/* Handle query commands. */
|
||||
if (kitty_get_action(ki) == 'q') {
|
||||
if (kitty_get_image_id(ki) != 0)
|
||||
input_reply(ictx, 0, "\033_Gi=%u;OK\033\\",
|
||||
kitty_get_image_id(ki));
|
||||
else
|
||||
input_reply(ictx, 0, "\033_Ga=q;OK\033\\");
|
||||
kitty_free(ki);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store image placements and trigger a redraw. */
|
||||
if (kitty_get_action(ki) == 'T' || kitty_get_action(ki) == 't' ||
|
||||
kitty_get_action(ki) == 'p') {
|
||||
screen_write_kittyimage(sctx, ki);
|
||||
} else {
|
||||
/* For other actions (delete, etc.), pass through. */
|
||||
char *apc;
|
||||
size_t apclen;
|
||||
|
||||
apclen = xasprintf(&apc, "\033_%s\033\\", ictx->input_buf);
|
||||
tty_kitty_passthrough(wp, apc, apclen, sctx->s->cx,
|
||||
sctx->s->cy);
|
||||
free(apc);
|
||||
kitty_free(ki);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* APC terminator (ST) received. */
|
||||
static void
|
||||
input_exit_apc(struct input_ctx *ictx)
|
||||
@@ -2805,13 +2727,6 @@ input_exit_apc(struct input_ctx *ictx)
|
||||
return;
|
||||
log_debug("%s: \"%s\"", __func__, ictx->input_buf);
|
||||
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
if (ictx->input_len >= 1 && ictx->input_buf[0] == 'G') {
|
||||
input_apc_kitty_image(ictx);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wp != NULL &&
|
||||
options_get_number(wp->options, "allow-set-title") &&
|
||||
screen_set_title(sctx->s, ictx->input_buf)) {
|
||||
|
||||
@@ -350,6 +350,10 @@ key_bindings_init(void)
|
||||
{
|
||||
static const char *const defaults[] = {
|
||||
/* Prefix keys. */
|
||||
"bind -N 'Minimise pane' _ { minimise-pane }",
|
||||
/* Mouse button 1 double click on status line. */
|
||||
"bind -n DoubleClick1Status { minimise-pane -t= }",
|
||||
|
||||
"bind -N 'Send the prefix key' C-b { send-prefix }",
|
||||
"bind -N 'Rotate through the panes' C-o { rotate-window }",
|
||||
"bind -N 'Suspend the current client' C-z { suspend-client }",
|
||||
@@ -361,6 +365,7 @@ key_bindings_init(void)
|
||||
"bind -N 'Split window horizontally' % { split-window -h }",
|
||||
"bind -N 'Kill current window' & { confirm-before -p\"kill-window #W? (y/n)\" kill-window }",
|
||||
"bind -N 'Prompt for window index to select' \"'\" { command-prompt -T window-target -pindex { select-window -t ':%%' } }",
|
||||
"bind -N 'New floating pane' * { new-pane }",
|
||||
"bind -N 'Switch to previous client' ( { switch-client -p }",
|
||||
"bind -N 'Switch to next client' ) { switch-client -n }",
|
||||
"bind -N 'Rename current window' , { command-prompt -I'#W' { rename-window -- '%%' } }",
|
||||
@@ -459,6 +464,9 @@ key_bindings_init(void)
|
||||
/* Mouse button 1 triple click on pane. */
|
||||
"bind -n TripleClick1Pane { select-pane -t=; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -H; send -X select-line; run -d0.3; send -X copy-pipe-and-cancel } }",
|
||||
|
||||
/* Mouse button 1 on border. */
|
||||
"bind -n MouseDown1Border { select-pane -M }",
|
||||
|
||||
/* Mouse button 1 drag on border. */
|
||||
"bind -n MouseDrag1Border { resize-pane -M }",
|
||||
|
||||
|
||||
180
layout-custom.c
180
layout-custom.c
@@ -27,10 +27,11 @@ static struct layout_cell *layout_find_bottomright(struct layout_cell *);
|
||||
static u_short layout_checksum(const char *);
|
||||
static int layout_append(struct layout_cell *, char *,
|
||||
size_t);
|
||||
static struct layout_cell *layout_construct(struct layout_cell *,
|
||||
const char **);
|
||||
static int layout_construct(struct layout_cell *,
|
||||
const char **, struct layout_cell **,
|
||||
struct layout_cell **);
|
||||
static void layout_assign(struct window_pane **,
|
||||
struct layout_cell *);
|
||||
struct layout_cell *, int);
|
||||
|
||||
/* Find the bottom-right cell. */
|
||||
static struct layout_cell *
|
||||
@@ -58,14 +59,33 @@ layout_checksum(const char *layout)
|
||||
|
||||
/* Dump layout as a string. */
|
||||
char *
|
||||
layout_dump(struct layout_cell *root)
|
||||
layout_dump(struct window *w, struct layout_cell *root)
|
||||
{
|
||||
char layout[8192], *out;
|
||||
char layout[8192], *out;
|
||||
int braket;
|
||||
struct window_pane *wp;
|
||||
|
||||
*layout = '\0';
|
||||
if (layout_append(root, layout, sizeof layout) != 0)
|
||||
return (NULL);
|
||||
|
||||
braket = 0;
|
||||
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||
if (~wp->flags & PANE_FLOATING)
|
||||
break;
|
||||
if (!braket) {
|
||||
strcat(layout, "<");
|
||||
braket = 1;
|
||||
}
|
||||
if (layout_append(wp->layout_cell, layout, sizeof layout) != 0)
|
||||
return (NULL);
|
||||
strcat(layout, ",");
|
||||
}
|
||||
if (braket) {
|
||||
/* Overwrite the trailing ','. */
|
||||
layout[strlen(layout) - 1] = '>';
|
||||
}
|
||||
|
||||
xasprintf(&out, "%04hx,%s", layout_checksum(layout), layout);
|
||||
return (out);
|
||||
}
|
||||
@@ -81,7 +101,8 @@ layout_append(struct layout_cell *lc, char *buf, size_t len)
|
||||
|
||||
if (len == 0)
|
||||
return (-1);
|
||||
|
||||
if (lc == NULL)
|
||||
return (0);
|
||||
if (lc->wp != NULL) {
|
||||
tmplen = xsnprintf(tmp, sizeof tmp, "%ux%u,%u,%u,%u",
|
||||
lc->sx, lc->sy, lc->xoff, lc->yoff, lc->wp->id);
|
||||
@@ -109,6 +130,7 @@ layout_append(struct layout_cell *lc, char *buf, size_t len)
|
||||
}
|
||||
buf[strlen(buf) - 1] = brackets[0];
|
||||
break;
|
||||
case LAYOUT_FLOATING:
|
||||
case LAYOUT_WINDOWPANE:
|
||||
break;
|
||||
}
|
||||
@@ -125,6 +147,7 @@ layout_check(struct layout_cell *lc)
|
||||
|
||||
switch (lc->type) {
|
||||
case LAYOUT_WINDOWPANE:
|
||||
case LAYOUT_FLOATING:
|
||||
break;
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
@@ -156,7 +179,7 @@ layout_check(struct layout_cell *lc)
|
||||
int
|
||||
layout_parse(struct window *w, const char *layout, char **cause)
|
||||
{
|
||||
struct layout_cell *lc, *lcchild;
|
||||
struct layout_cell *lcchild, *tiled_lc = NULL, *floating_lc = NULL;
|
||||
struct window_pane *wp;
|
||||
u_int npanes, ncells, sx = 0, sy = 0;
|
||||
u_short csum;
|
||||
@@ -173,11 +196,16 @@ layout_parse(struct window *w, const char *layout, char **cause)
|
||||
}
|
||||
|
||||
/* Build the layout. */
|
||||
lc = layout_construct(NULL, &layout);
|
||||
if (lc == NULL) {
|
||||
if (layout_construct(NULL, &layout, &tiled_lc, &floating_lc) != 0) {
|
||||
*cause = xstrdup("invalid layout");
|
||||
return (-1);
|
||||
}
|
||||
if (tiled_lc == NULL) {
|
||||
/* A stub layout cell for an empty window. */
|
||||
tiled_lc = layout_create_cell(NULL);
|
||||
tiled_lc->type = LAYOUT_LEFTRIGHT;
|
||||
layout_set_size(tiled_lc, w->sx, w->sy, 0, 0);
|
||||
}
|
||||
if (*layout != '\0') {
|
||||
*cause = xstrdup("invalid layout");
|
||||
goto fail;
|
||||
@@ -186,8 +214,10 @@ layout_parse(struct window *w, const char *layout, char **cause)
|
||||
/* Check this window will fit into the layout. */
|
||||
for (;;) {
|
||||
npanes = window_count_panes(w);
|
||||
ncells = layout_count_cells(lc);
|
||||
ncells = layout_count_cells(tiled_lc);
|
||||
ncells += layout_count_cells(floating_lc);
|
||||
if (npanes > ncells) {
|
||||
/* Modify this to open a new pane */
|
||||
xasprintf(cause, "have %u panes but need %u", npanes,
|
||||
ncells);
|
||||
goto fail;
|
||||
@@ -195,9 +225,17 @@ layout_parse(struct window *w, const char *layout, char **cause)
|
||||
if (npanes == ncells)
|
||||
break;
|
||||
|
||||
/* Fewer panes than cells - close the bottom right. */
|
||||
lcchild = layout_find_bottomright(lc);
|
||||
layout_destroy_cell(w, lcchild, &lc);
|
||||
/*
|
||||
* Fewer panes than cells - close floating panes first
|
||||
* then close the bottom right until.
|
||||
*/
|
||||
if (floating_lc && ! TAILQ_EMPTY(&floating_lc->cells)) {
|
||||
lcchild = TAILQ_FIRST(&floating_lc->cells);
|
||||
layout_destroy_cell(w, lcchild, &floating_lc);
|
||||
} else {
|
||||
lcchild = layout_find_bottomright(tiled_lc);
|
||||
layout_destroy_cell(w, lcchild, &tiled_lc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -205,85 +243,112 @@ layout_parse(struct window *w, const char *layout, char **cause)
|
||||
* an incorrect top cell size - if it is larger than the top child then
|
||||
* correct that (if this is still wrong the check code will catch it).
|
||||
*/
|
||||
switch (lc->type) {
|
||||
|
||||
switch (tiled_lc->type) {
|
||||
case LAYOUT_WINDOWPANE:
|
||||
break;
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
TAILQ_FOREACH(lcchild, &tiled_lc->cells, entry) {
|
||||
sy = lcchild->sy + 1;
|
||||
sx += lcchild->sx + 1;
|
||||
}
|
||||
break;
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
TAILQ_FOREACH(lcchild, &tiled_lc->cells, entry) {
|
||||
sx = lcchild->sx + 1;
|
||||
sy += lcchild->sy + 1;
|
||||
}
|
||||
break;
|
||||
case LAYOUT_FLOATING:
|
||||
*cause = xstrdup("invalid layout");
|
||||
goto fail;
|
||||
}
|
||||
if (lc->type != LAYOUT_WINDOWPANE && (lc->sx != sx || lc->sy != sy)) {
|
||||
log_debug("fix layout %u,%u to %u,%u", lc->sx, lc->sy, sx,sy);
|
||||
layout_print_cell(lc, __func__, 0);
|
||||
lc->sx = sx - 1; lc->sy = sy - 1;
|
||||
if (tiled_lc->type != LAYOUT_WINDOWPANE &&
|
||||
(tiled_lc->sx != sx || tiled_lc->sy != sy)) {
|
||||
log_debug("fix layout %u,%u to %u,%u", tiled_lc->sx,
|
||||
tiled_lc->sy, sx,sy);
|
||||
layout_print_cell(tiled_lc, __func__, 0);
|
||||
tiled_lc->sx = sx - 1; tiled_lc->sy = sy - 1;
|
||||
}
|
||||
|
||||
/* Check the new layout. */
|
||||
if (!layout_check(lc)) {
|
||||
if (!layout_check(tiled_lc)) {
|
||||
*cause = xstrdup("size mismatch after applying layout");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Resize to the layout size. */
|
||||
window_resize(w, lc->sx, lc->sy, -1, -1);
|
||||
/* Resize window to the layout size. */
|
||||
if (sx != 0 && sy != 0)
|
||||
window_resize(w, tiled_lc->sx, tiled_lc->sy, -1, -1);
|
||||
|
||||
/* Destroy the old layout and swap to the new. */
|
||||
layout_free_cell(w->layout_root);
|
||||
w->layout_root = lc;
|
||||
w->layout_root = tiled_lc;
|
||||
|
||||
/* Assign the panes into the cells. */
|
||||
wp = TAILQ_FIRST(&w->panes);
|
||||
layout_assign(&wp, lc);
|
||||
layout_assign(&wp, tiled_lc, 0);
|
||||
layout_assign(&wp, floating_lc, 1);
|
||||
|
||||
/* Fix z_indexes. */
|
||||
while (!TAILQ_EMPTY(&w->z_index)) {
|
||||
wp = TAILQ_FIRST(&w->z_index);
|
||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||
}
|
||||
layout_fix_zindexes(w, floating_lc);
|
||||
layout_fix_zindexes(w, tiled_lc);
|
||||
|
||||
/* Update pane offsets and sizes. */
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w, NULL);
|
||||
recalculate_sizes();
|
||||
|
||||
layout_print_cell(lc, __func__, 0);
|
||||
layout_print_cell(tiled_lc, __func__, 0);
|
||||
layout_print_cell(floating_lc, __func__, 0);
|
||||
|
||||
/* Free the floating layout cell, no longer needed. */
|
||||
layout_free_cell(floating_lc);
|
||||
|
||||
notify_window("window-layout-changed", w);
|
||||
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
layout_free_cell(lc);
|
||||
layout_free_cell(tiled_lc);
|
||||
layout_free_cell(floating_lc);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Assign panes into cells. */
|
||||
static void
|
||||
layout_assign(struct window_pane **wp, struct layout_cell *lc)
|
||||
layout_assign(struct window_pane **wp, struct layout_cell *lc, int floating)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
|
||||
if (lc == NULL)
|
||||
return;
|
||||
|
||||
switch (lc->type) {
|
||||
case LAYOUT_WINDOWPANE:
|
||||
layout_make_leaf(lc, *wp);
|
||||
if (floating) {
|
||||
(*wp)->flags |= PANE_FLOATING;
|
||||
}
|
||||
*wp = TAILQ_NEXT(*wp, entry);
|
||||
return;
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
case LAYOUT_FLOATING:
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||
layout_assign(wp, lcchild);
|
||||
layout_assign(wp, lcchild, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct a cell from all or part of a layout tree. */
|
||||
static struct layout_cell *
|
||||
layout_construct(struct layout_cell *lcparent, const char **layout)
|
||||
layout_construct_cell(struct layout_cell *lcparent, const char **layout)
|
||||
{
|
||||
struct layout_cell *lc, *lcchild;
|
||||
struct layout_cell *lc;
|
||||
u_int sx, sy, xoff, yoff;
|
||||
const char *saved;
|
||||
|
||||
@@ -324,17 +389,42 @@ layout_construct(struct layout_cell *lcparent, const char **layout)
|
||||
lc->xoff = xoff;
|
||||
lc->yoff = yoff;
|
||||
|
||||
return (lc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Given a character string layout, recursively construct cells.
|
||||
* Possible return values:
|
||||
* lc LAYOUT_WINDOWPANE, no children
|
||||
* lc LAYOUT_LEFTRIGHT or LAYOUT_TOPBOTTOM, with children
|
||||
* floating_lc LAYOUT_FLOATING, with children
|
||||
*/
|
||||
static int
|
||||
layout_construct(struct layout_cell *lcparent, const char **layout,
|
||||
struct layout_cell **lc, struct layout_cell **floating_lc)
|
||||
{
|
||||
struct layout_cell *lcchild, *saved_lc;
|
||||
|
||||
*lc = layout_construct_cell(lcparent, layout);
|
||||
|
||||
switch (**layout) {
|
||||
case ',':
|
||||
case '}':
|
||||
case ']':
|
||||
case '>':
|
||||
case '\0':
|
||||
return (lc);
|
||||
return (0);
|
||||
case '{':
|
||||
lc->type = LAYOUT_LEFTRIGHT;
|
||||
(*lc)->type = LAYOUT_LEFTRIGHT;
|
||||
break;
|
||||
case '[':
|
||||
lc->type = LAYOUT_TOPBOTTOM;
|
||||
(*lc)->type = LAYOUT_TOPBOTTOM;
|
||||
break;
|
||||
case '<':
|
||||
saved_lc = *lc;
|
||||
*lc = layout_create_cell(lcparent);
|
||||
(*lc)->type = LAYOUT_FLOATING;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
@@ -342,13 +432,12 @@ layout_construct(struct layout_cell *lcparent, const char **layout)
|
||||
|
||||
do {
|
||||
(*layout)++;
|
||||
lcchild = layout_construct(lc, layout);
|
||||
if (lcchild == NULL)
|
||||
if (layout_construct(*lc, layout, &lcchild, floating_lc) != 0)
|
||||
goto fail;
|
||||
TAILQ_INSERT_TAIL(&lc->cells, lcchild, entry);
|
||||
TAILQ_INSERT_TAIL(&(*lc)->cells, lcchild, entry);
|
||||
} while (**layout == ',');
|
||||
|
||||
switch (lc->type) {
|
||||
switch ((*lc)->type) {
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
if (**layout != '}')
|
||||
goto fail;
|
||||
@@ -357,14 +446,21 @@ layout_construct(struct layout_cell *lcparent, const char **layout)
|
||||
if (**layout != ']')
|
||||
goto fail;
|
||||
break;
|
||||
case LAYOUT_FLOATING:
|
||||
if (**layout != '>')
|
||||
goto fail;
|
||||
*floating_lc = *lc;
|
||||
*lc = saved_lc;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
(*layout)++;
|
||||
|
||||
return (lc);
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
layout_free_cell(lc);
|
||||
return (NULL);
|
||||
layout_free_cell(*lc);
|
||||
layout_free_cell(*floating_lc);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
175
layout.c
175
layout.c
@@ -83,9 +83,24 @@ layout_free_cell(struct layout_cell *lc)
|
||||
layout_free_cell(lcchild);
|
||||
}
|
||||
break;
|
||||
case LAYOUT_FLOATING:
|
||||
/* A Floating layout cell is only used temporarily
|
||||
* while select-layout constructs a layout.
|
||||
* Cleave the children from the temp layout, then
|
||||
* free temp floating layout cell. Each floating
|
||||
* pane has stub layout.
|
||||
*/
|
||||
while (!TAILQ_EMPTY(&lc->cells)) {
|
||||
lcchild = TAILQ_FIRST(&lc->cells);
|
||||
TAILQ_REMOVE(&lc->cells, lcchild, entry);
|
||||
lcchild->parent = NULL;
|
||||
}
|
||||
break;
|
||||
case LAYOUT_WINDOWPANE:
|
||||
if (lc->wp != NULL)
|
||||
if (lc->wp != NULL) {
|
||||
lc->wp->layout_cell->parent = NULL;
|
||||
lc->wp->layout_cell = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -98,6 +113,9 @@ layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
|
||||
struct layout_cell *lcchild;
|
||||
const char *type;
|
||||
|
||||
if (lc == NULL)
|
||||
return;
|
||||
|
||||
switch (lc->type) {
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
type = "LEFTRIGHT";
|
||||
@@ -105,6 +123,9 @@ layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
type = "TOPBOTTOM";
|
||||
break;
|
||||
case LAYOUT_FLOATING:
|
||||
type = "FLOATING";
|
||||
break;
|
||||
case LAYOUT_WINDOWPANE:
|
||||
type = "WINDOWPANE";
|
||||
break;
|
||||
@@ -118,6 +139,7 @@ layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n)
|
||||
switch (lc->type) {
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
case LAYOUT_FLOATING:
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||
layout_print_cell(lcchild, hdr, n + 1);
|
||||
break;
|
||||
@@ -153,6 +175,7 @@ layout_search_by_border(struct layout_cell *lc, u_int x, u_int y)
|
||||
return (last);
|
||||
break;
|
||||
case LAYOUT_WINDOWPANE:
|
||||
case LAYOUT_FLOATING:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -198,6 +221,29 @@ layout_make_node(struct layout_cell *lc, enum layout_type type)
|
||||
lc->wp = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
layout_fix_zindexes(struct window *w, struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *lcchild;
|
||||
|
||||
if (lc == NULL)
|
||||
return;
|
||||
|
||||
switch (lc->type) {
|
||||
case LAYOUT_WINDOWPANE:
|
||||
TAILQ_INSERT_TAIL(&w->z_index, lc->wp, zentry);
|
||||
break;
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
case LAYOUT_FLOATING:
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||
layout_fix_zindexes(w, lcchild);
|
||||
return;
|
||||
default:
|
||||
fatalx("bad layout type");
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix cell offsets for a child cell. */
|
||||
static void
|
||||
layout_fix_offsets1(struct layout_cell *lc)
|
||||
@@ -208,6 +254,9 @@ layout_fix_offsets1(struct layout_cell *lc)
|
||||
if (lc->type == LAYOUT_LEFTRIGHT) {
|
||||
xoff = lc->xoff;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (lcchild->type == LAYOUT_WINDOWPANE &&
|
||||
lcchild->wp->flags & PANE_MINIMISED)
|
||||
continue;
|
||||
lcchild->xoff = xoff;
|
||||
lcchild->yoff = lc->yoff;
|
||||
if (lcchild->type != LAYOUT_WINDOWPANE)
|
||||
@@ -217,6 +266,8 @@ layout_fix_offsets1(struct layout_cell *lc)
|
||||
} else {
|
||||
yoff = lc->yoff;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (lcchild->wp->flags & PANE_MINIMISED)
|
||||
continue;
|
||||
lcchild->xoff = lc->xoff;
|
||||
lcchild->yoff = yoff;
|
||||
if (lcchild->type != LAYOUT_WINDOWPANE)
|
||||
@@ -307,7 +358,8 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
|
||||
sx = lc->sx;
|
||||
sy = lc->sy;
|
||||
|
||||
if (layout_add_horizontal_border(w, lc, status)) {
|
||||
if (~wp->flags & PANE_FLOATING &&
|
||||
layout_add_horizontal_border(w, lc, status)) {
|
||||
if (status == PANE_STATUS_TOP)
|
||||
wp->yoff++;
|
||||
sy--;
|
||||
@@ -353,6 +405,7 @@ layout_count_cells(struct layout_cell *lc)
|
||||
return (1);
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
case LAYOUT_FLOATING:
|
||||
count = 0;
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry)
|
||||
count += layout_count_cells(lcchild);
|
||||
@@ -462,7 +515,7 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
|
||||
}
|
||||
}
|
||||
|
||||
/* Destroy a cell and redistribute the space. */
|
||||
/* Destroy a cell and redistribute the space in tiled cells. */
|
||||
void
|
||||
layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
||||
struct layout_cell **lcroot)
|
||||
@@ -470,13 +523,66 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
||||
struct layout_cell *lcother, *lcparent;
|
||||
|
||||
/*
|
||||
* If no parent, this is the last pane so window close is imminent and
|
||||
* there is no need to resize anything.
|
||||
* If no parent, this is either a floating pane or the last
|
||||
* pane so window close is imminent and there is no need to
|
||||
* resize anything.
|
||||
*/
|
||||
lcparent = lc->parent;
|
||||
if (lcparent == NULL) {
|
||||
if (lc->wp != NULL && ~lc->wp->flags & PANE_FLOATING)
|
||||
*lcroot = NULL;
|
||||
layout_free_cell(lc);
|
||||
*lcroot = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* In tiled layouts, merge the space into the previous or next cell. */
|
||||
if (lcparent->type != LAYOUT_FLOATING) {
|
||||
if (lc == TAILQ_FIRST(&lcparent->cells))
|
||||
lcother = TAILQ_NEXT(lc, entry);
|
||||
else
|
||||
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
||||
if (lcother != NULL && lcparent->type == LAYOUT_LEFTRIGHT)
|
||||
layout_resize_adjust(w, lcother, lcparent->type, lc->sx + 1);
|
||||
else if (lcother != NULL)
|
||||
layout_resize_adjust(w, lcother, lcparent->type, lc->sy + 1);
|
||||
}
|
||||
|
||||
/* Remove this from the parent's list. */
|
||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||
layout_free_cell(lc);
|
||||
|
||||
if (lcparent->type == LAYOUT_FLOATING)
|
||||
return;
|
||||
|
||||
/*
|
||||
* In tiled layouts, if the parent now has one cell, remove
|
||||
* the parent from the tree and replace it by that cell.
|
||||
*/
|
||||
lc = TAILQ_FIRST(&lcparent->cells);
|
||||
if (lc != NULL && TAILQ_NEXT(lc, entry) == NULL) {
|
||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||
|
||||
lc->parent = lcparent->parent;
|
||||
if (lc->parent == NULL) {
|
||||
lc->xoff = 0; lc->yoff = 0;
|
||||
*lcroot = lc;
|
||||
} else
|
||||
TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
|
||||
|
||||
layout_free_cell(lcparent);
|
||||
}
|
||||
}
|
||||
|
||||
/* Minimise a cell and redistribute the space in tiled cells. */
|
||||
void
|
||||
layout_minimise_cell(struct window *w, struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *lcother, *lcparent, *lcchild;
|
||||
u_int space = 0;
|
||||
|
||||
lcparent = lc->parent;
|
||||
if (lcparent == NULL ||
|
||||
lcparent->type == LAYOUT_FLOATING) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -490,26 +596,44 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
|
||||
else if (lcother != NULL)
|
||||
layout_resize_adjust(w, lcother, lcparent->type, lc->sy + 1);
|
||||
|
||||
/* Remove this from the parent's list. */
|
||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||
layout_free_cell(lc);
|
||||
/* If the parent cells are all minimised, minimise it too. */
|
||||
if (lcparent != NULL) {
|
||||
TAILQ_FOREACH(lcchild, &lcparent->cells, entry) {
|
||||
if (lcchild->wp == NULL ||
|
||||
lcchild->wp->flags & PANE_MINIMISED)
|
||||
continue;
|
||||
if (lcparent->type == LAYOUT_LEFTRIGHT) {
|
||||
space += lcchild->sx;
|
||||
} else if (lcparent->type == LAYOUT_TOPBOTTOM) {
|
||||
space += lcchild->sy;
|
||||
}
|
||||
}
|
||||
if (space == 0)
|
||||
layout_minimise_cell(w, lcparent);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the parent now has one cell, remove the parent from the tree and
|
||||
* replace it by that cell.
|
||||
*/
|
||||
lc = TAILQ_FIRST(&lcparent->cells);
|
||||
if (TAILQ_NEXT(lc, entry) == NULL) {
|
||||
TAILQ_REMOVE(&lcparent->cells, lc, entry);
|
||||
/* Unminimise a cell and redistribute the space in tiled cells. */
|
||||
void
|
||||
layout_unminimise_cell(struct window *w, struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *lcother, *lcparent;
|
||||
|
||||
lc->parent = lcparent->parent;
|
||||
if (lc->parent == NULL) {
|
||||
lc->xoff = 0; lc->yoff = 0;
|
||||
*lcroot = lc;
|
||||
} else
|
||||
TAILQ_REPLACE(&lc->parent->cells, lcparent, lc, entry);
|
||||
lcparent = lc->parent;
|
||||
if (lcparent == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
layout_free_cell(lcparent);
|
||||
/* In tiled layouts, merge the space into the previous or next cell. */
|
||||
if (lcparent->type != LAYOUT_FLOATING) {
|
||||
if (lc == TAILQ_FIRST(&lcparent->cells))
|
||||
lcother = TAILQ_NEXT(lc, entry);
|
||||
else
|
||||
lcother = TAILQ_PREV(lc, layout_cells, entry);
|
||||
if (lcother != NULL && lcparent->type == LAYOUT_LEFTRIGHT)
|
||||
layout_resize_adjust(w, lcother, lcparent->type, -(lc->sx + 1));
|
||||
else if (lcother != NULL)
|
||||
layout_resize_adjust(w, lcother, lcparent->type, -(lc->sy + 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,7 +865,7 @@ layout_resize_pane_shrink(struct window *w, struct layout_cell *lc,
|
||||
return (size);
|
||||
}
|
||||
|
||||
/* Assign window pane to newly split cell. */
|
||||
/* Assign window pane to new cell. */
|
||||
void
|
||||
layout_assign_pane(struct layout_cell *lc, struct window_pane *wp,
|
||||
int do_not_resize)
|
||||
@@ -1085,6 +1209,9 @@ layout_close_pane(struct window_pane *wp)
|
||||
{
|
||||
struct window *w = wp->window;
|
||||
|
||||
if (wp->layout_cell == NULL)
|
||||
return;
|
||||
|
||||
/* Remove the cell. */
|
||||
layout_destroy_cell(w, wp->layout_cell, &w->layout_root);
|
||||
|
||||
|
||||
774
screen-redraw.c
774
screen-redraw.c
File diff suppressed because it is too large
Load Diff
452
screen-write.c
452
screen-write.c
@@ -36,6 +36,7 @@ static int screen_write_overwrite(struct screen_write_ctx *,
|
||||
struct grid_cell *, u_int);
|
||||
static int screen_write_combine(struct screen_write_ctx *,
|
||||
const struct grid_cell *);
|
||||
static int screen_write_pane_obscured(struct window_pane *);
|
||||
|
||||
struct screen_write_citem {
|
||||
u_int x;
|
||||
@@ -574,6 +575,8 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
|
||||
struct grid *gd = src->grid;
|
||||
struct grid_cell gc;
|
||||
u_int xx, yy, cx = s->cx, cy = s->cy;
|
||||
int yoff = 0;
|
||||
struct visible_ranges *r;
|
||||
|
||||
if (nx == 0 || ny == 0)
|
||||
return;
|
||||
@@ -582,17 +585,24 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
|
||||
if (yy >= gd->hsize + gd->sy)
|
||||
break;
|
||||
s->cx = cx;
|
||||
if (wp != NULL)
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
if (wp != NULL) {
|
||||
yoff = wp->yoff;
|
||||
}
|
||||
r = screen_redraw_get_visible_ranges(wp, px, s->cy + yoff, nx,
|
||||
NULL);
|
||||
for (xx = px; xx < px + nx; xx++) {
|
||||
if (xx >= grid_get_line(gd, yy)->cellsize &&
|
||||
s->cx >= grid_get_line(ctx->s->grid, s->cy)->cellsize)
|
||||
s->cx >= grid_get_line(ctx->s->grid,
|
||||
s->cy)->cellsize)
|
||||
break;
|
||||
grid_get_cell(gd, xx, yy, &gc);
|
||||
if (xx + gc.data.width > px + nx)
|
||||
break;
|
||||
grid_view_set_cell(ctx->s->grid, s->cx, s->cy, &gc);
|
||||
if (wp != NULL) {
|
||||
if (! screen_redraw_is_visible(r, px))
|
||||
break;
|
||||
ttyctx.cell = &gc;
|
||||
tty_write(tty_cmd_cell, &ttyctx);
|
||||
ttyctx.ocx++;
|
||||
@@ -1072,7 +1082,7 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
|
||||
memcpy(&gc, &grid_default_cell, sizeof gc);
|
||||
utf8_set(&gc.data, 'E');
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_free_all(s) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1111,7 +1121,7 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
|
||||
if (s->cx > screen_size_x(s) - 1)
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_check_line(s, s->cy, 1) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1144,7 +1154,7 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
|
||||
if (s->cx > screen_size_x(s) - 1)
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_check_line(s, s->cy, 1) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1177,7 +1187,7 @@ screen_write_clearcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
|
||||
if (s->cx > screen_size_x(s) - 1)
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_check_line(s, s->cy, 1) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1200,14 +1210,14 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
|
||||
struct grid *gd = s->grid;
|
||||
struct tty_ctx ttyctx;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
u_int sy = screen_size_y(s);
|
||||
#endif
|
||||
|
||||
if (ny == 0)
|
||||
ny = 1;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_check_line(s, s->cy, sy - s->cy) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1260,7 +1270,7 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
|
||||
if (ny == 0)
|
||||
ny = 1;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_check_line(s, s->cy, sy - s->cy) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1313,7 +1323,7 @@ screen_write_clearline(struct screen_write_ctx *ctx, u_int bg)
|
||||
if (gl->cellsize == 0 && COLOUR_DEFAULT(bg))
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_check_line(s, s->cy, 1) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1347,7 +1357,7 @@ screen_write_clearendofline(struct screen_write_ctx *ctx, u_int bg)
|
||||
if (s->cx > sx - 1 || (s->cx >= gl->cellsize && COLOUR_DEFAULT(bg)))
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_check_line(s, s->cy, 1) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1374,7 +1384,7 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_check_line(s, s->cy, 1) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1391,6 +1401,23 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
|
||||
screen_write_collect_insert(ctx, ci);
|
||||
}
|
||||
|
||||
/* Clear part of a line from px for nx columns. */
|
||||
static void
|
||||
screen_write_clearpartofline(struct screen_write_ctx *ctx, u_int px, u_int nx,
|
||||
u_int bg)
|
||||
{
|
||||
struct screen_write_citem *ci = ctx->item;
|
||||
|
||||
if (nx == 0)
|
||||
return;
|
||||
|
||||
ci->x = px;
|
||||
ci->used = nx;
|
||||
ci->type = CLEAR;
|
||||
ci->bg = bg;
|
||||
screen_write_collect_insert(ctx, ci);
|
||||
}
|
||||
|
||||
/* Move cursor to px,py. */
|
||||
void
|
||||
screen_write_cursormove(struct screen_write_ctx *ctx, int px, int py,
|
||||
@@ -1422,7 +1449,7 @@ screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg)
|
||||
struct tty_ctx ttyctx;
|
||||
|
||||
if (s->cy == s->rupper) {
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_free_all(s) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1469,7 +1496,7 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped, u_int bg)
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
struct grid_line *gl;
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
int redraw = 0;
|
||||
#endif
|
||||
u_int rupper = s->rupper, rlower = s->rlower;
|
||||
@@ -1487,7 +1514,7 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped, u_int bg)
|
||||
}
|
||||
|
||||
if (s->cy == s->rlower) {
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (rlower == screen_size_y(s) - 1)
|
||||
redraw = image_scroll_up(s, 1);
|
||||
else
|
||||
@@ -1520,7 +1547,7 @@ screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines, u_int bg)
|
||||
ctx->bg = bg;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_scroll_up(s, lines) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1549,7 +1576,7 @@ screen_write_scrolldown(struct screen_write_ctx *ctx, u_int lines, u_int bg)
|
||||
else if (lines > s->rlower - s->rupper + 1)
|
||||
lines = s->rlower - s->rupper + 1;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_free_all(s) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1573,12 +1600,15 @@ screen_write_carriagereturn(struct screen_write_ctx *ctx)
|
||||
void
|
||||
screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
struct screen *s = ctx->s;
|
||||
struct grid *gd = s->grid;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
u_int y, i, xoff, yoff, cx_save, cy_save;
|
||||
struct visible_ranges *r;
|
||||
struct visible_range *ri;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_check_line(s, s->cy, sy - s->cy) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1601,18 +1631,66 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
|
||||
|
||||
screen_write_collect_clear(ctx, s->cy + 1, sy - (s->cy + 1));
|
||||
screen_write_collect_flush(ctx, 0, __func__);
|
||||
tty_write(tty_cmd_clearendofscreen, &ttyctx);
|
||||
|
||||
if (! screen_write_pane_obscured(ctx->wp)) {
|
||||
tty_write(tty_cmd_clearendofscreen, &ttyctx);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Can't just clear screen, must avoid floating windows. */
|
||||
cx_save = s->cx;
|
||||
cy_save = s->cy;
|
||||
if (ctx->wp != NULL) {
|
||||
xoff = ctx->wp->xoff;
|
||||
yoff = ctx->wp->yoff;
|
||||
} else {
|
||||
xoff = 0;
|
||||
yoff = 0;
|
||||
}
|
||||
|
||||
/* First line: visible ranges from the current cursor to end. */
|
||||
if (s->cx <= sx - 1) {
|
||||
r = screen_redraw_get_visible_ranges(ctx->wp,
|
||||
xoff + s->cx, yoff + s->cy, sx - s->cx, NULL);
|
||||
for (i = 0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx == 0)
|
||||
continue;
|
||||
screen_write_clearpartofline(ctx,
|
||||
ri->px - xoff, ri->nx, bg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remaining lines: visible ranges across the full width. */
|
||||
for (y = s->cy + 1; y < sy; y++) {
|
||||
screen_write_set_cursor(ctx, 0, y);
|
||||
r = screen_redraw_get_visible_ranges(ctx->wp,
|
||||
xoff, yoff + y, sx, NULL);
|
||||
for (i = 0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx == 0)
|
||||
continue;
|
||||
screen_write_clearpartofline(ctx,
|
||||
ri->px - xoff, ri->nx, bg);
|
||||
}
|
||||
}
|
||||
|
||||
screen_write_collect_flush(ctx, 0, __func__);
|
||||
screen_write_set_cursor(ctx, cx_save, cy_save);
|
||||
}
|
||||
|
||||
/* Clear to start of screen. */
|
||||
void
|
||||
screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s);
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s);
|
||||
u_int y, i, xoff, yoff, cx_save, cy_save;
|
||||
struct visible_ranges *r;
|
||||
struct visible_range *ri;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_check_line(s, 0, s->cy - 1) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1629,18 +1707,64 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
|
||||
|
||||
screen_write_collect_clear(ctx, 0, s->cy);
|
||||
screen_write_collect_flush(ctx, 0, __func__);
|
||||
tty_write(tty_cmd_clearstartofscreen, &ttyctx);
|
||||
|
||||
if (! screen_write_pane_obscured(ctx->wp)) {
|
||||
tty_write(tty_cmd_clearstartofscreen, &ttyctx);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Can't just clear screen, must avoid floating windows. */
|
||||
cx_save = s->cx;
|
||||
cy_save = s->cy;
|
||||
if (ctx->wp != NULL) {
|
||||
xoff = ctx->wp->xoff;
|
||||
yoff = ctx->wp->yoff;
|
||||
} else {
|
||||
xoff = 0;
|
||||
yoff = 0;
|
||||
}
|
||||
|
||||
/* Lines 0 to cy-1: visible ranges across the full width. */
|
||||
for (y = 0; y < s->cy; y++) {
|
||||
screen_write_set_cursor(ctx, 0, y);
|
||||
r = screen_redraw_get_visible_ranges(ctx->wp,
|
||||
xoff, yoff + y, sx, NULL);
|
||||
for (i = 0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx == 0)
|
||||
continue;
|
||||
screen_write_clearpartofline(ctx,
|
||||
ri->px - xoff, ri->nx, bg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Last line: visible ranges from 0 to cursor (inclusive). */
|
||||
screen_write_set_cursor(ctx, 0, s->cy);
|
||||
r = screen_redraw_get_visible_ranges(ctx->wp,
|
||||
xoff, yoff + cy_save, s->cx + 1, NULL);
|
||||
for (i = 0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx == 0)
|
||||
continue;
|
||||
screen_write_clearpartofline(ctx, ri->px - xoff, ri->nx, bg);
|
||||
}
|
||||
|
||||
screen_write_collect_flush(ctx, 0, __func__);
|
||||
screen_write_set_cursor(ctx, cx_save, cy_save);
|
||||
}
|
||||
|
||||
/* Clear entire screen. */
|
||||
void
|
||||
screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
u_int y, i, xoff, yoff, cx_save, cy_save;
|
||||
struct visible_ranges *r;
|
||||
struct visible_range *ri;
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_free_all(s) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -1657,7 +1781,38 @@ screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
|
||||
grid_view_clear(s->grid, 0, 0, sx, sy, bg);
|
||||
|
||||
screen_write_collect_clear(ctx, 0, sy);
|
||||
tty_write(tty_cmd_clearscreen, &ttyctx);
|
||||
|
||||
if (! screen_write_pane_obscured(ctx->wp)) {
|
||||
tty_write(tty_cmd_clearscreen, &ttyctx);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Can't just clear screen, must avoid floating windows. */
|
||||
cx_save = s->cx;
|
||||
cy_save = s->cy;
|
||||
if (ctx->wp != NULL) {
|
||||
xoff = ctx->wp->xoff;
|
||||
yoff = ctx->wp->yoff;
|
||||
} else {
|
||||
xoff = 0;
|
||||
yoff = 0;
|
||||
}
|
||||
|
||||
for (y = 0; y < sy; y++) {
|
||||
screen_write_set_cursor(ctx, 0, y);
|
||||
r = screen_redraw_get_visible_ranges(ctx->wp,
|
||||
xoff, yoff + y, sx, NULL);
|
||||
for (i = 0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx == 0)
|
||||
continue;
|
||||
screen_write_clearpartofline(ctx,
|
||||
ri->px - xoff, ri->nx, bg);
|
||||
}
|
||||
}
|
||||
|
||||
screen_write_collect_flush(ctx, 0, __func__);
|
||||
screen_write_set_cursor(ctx, cx_save, cy_save);
|
||||
}
|
||||
|
||||
/* Clear entire history. */
|
||||
@@ -1809,6 +1964,39 @@ screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
|
||||
TAILQ_INSERT_TAIL(&ctx->s->write_list[s->rlower].items, ci, entry);
|
||||
}
|
||||
|
||||
/* Return 1 if there is a floating window pane overlapping this pane. */
|
||||
static int
|
||||
screen_write_pane_obscured(struct window_pane *base_wp)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
struct window *w;
|
||||
int found_self = 0;
|
||||
|
||||
if (base_wp == NULL)
|
||||
return(0);
|
||||
w = base_wp->window;
|
||||
|
||||
/* Check if there is a floating pane. xxxx borders? scrollbars? */
|
||||
TAILQ_FOREACH_REVERSE(wp, &w->z_index, window_panes_zindex, zentry) {
|
||||
if (wp == base_wp) {
|
||||
found_self = 1;
|
||||
continue;
|
||||
}
|
||||
if (found_self && wp->flags & PANE_FLOATING &&
|
||||
! (wp->flags & PANE_MINIMISED) &&
|
||||
((wp->yoff >= base_wp->yoff &&
|
||||
wp->yoff <= base_wp->yoff + (int)base_wp->sy) ||
|
||||
(wp->yoff + (int)wp->sy >= base_wp->yoff &&
|
||||
wp->yoff + wp->sy <= base_wp->yoff + base_wp->sy)) &&
|
||||
((wp->xoff >= base_wp->xoff &&
|
||||
wp->xoff <= base_wp->xoff + (int)base_wp->sx) ||
|
||||
(wp->xoff + (int)wp->sx >= base_wp->xoff &&
|
||||
wp->xoff + wp->sx <= base_wp->xoff + base_wp->sx)))
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Flush collected lines. */
|
||||
static void
|
||||
screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
||||
@@ -1817,8 +2005,14 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
||||
struct screen *s = ctx->s;
|
||||
struct screen_write_citem *ci, *tmp;
|
||||
struct screen_write_cline *cl;
|
||||
u_int y, cx, cy, last, items = 0;
|
||||
u_int y, cx, cy, last, items = 0, i;
|
||||
u_int wr_start, wr_end, wr_length, wsx, wsy;
|
||||
int r_start, r_end, ci_start, ci_end;
|
||||
int xoff, yoff;
|
||||
struct tty_ctx ttyctx;
|
||||
struct visible_ranges *r;
|
||||
struct visible_range *ri;
|
||||
struct window_pane *wp = ctx->wp;
|
||||
|
||||
if (s->mode & MODE_SYNC) {
|
||||
for (y = 0; y < screen_size_y(s); y++) {
|
||||
@@ -1838,11 +2032,14 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
||||
ctx->scrolled = s->rlower - s->rupper + 1;
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 1);
|
||||
if (wp != NULL && wp->yoff + wp->sy > wp->window->sy)
|
||||
ttyctx.orlower -= (wp->yoff + wp->sy - wp->window->sy);
|
||||
ttyctx.num = ctx->scrolled;
|
||||
ttyctx.bg = ctx->bg;
|
||||
ttyctx.obscured = screen_write_pane_obscured(wp);
|
||||
tty_write(tty_cmd_scrollup, &ttyctx);
|
||||
|
||||
if (ctx->wp != NULL)
|
||||
if (wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAWSCROLLBAR;
|
||||
}
|
||||
ctx->scrolled = 0;
|
||||
@@ -1852,8 +2049,29 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
||||
return;
|
||||
|
||||
cx = s->cx; cy = s->cy;
|
||||
|
||||
/* The xoff and width of window pane relative to the window we
|
||||
* are writing to relative to the visible_ranges array. */
|
||||
if (wp != NULL) {
|
||||
wsx = wp->window->sx;
|
||||
wsy = wp->window->sy;
|
||||
xoff = wp->xoff;
|
||||
yoff = wp->yoff;
|
||||
} else {
|
||||
wsx = screen_size_x(s);
|
||||
wsy = screen_size_y(s);
|
||||
xoff = 0;
|
||||
yoff = 0;
|
||||
}
|
||||
|
||||
for (y = 0; y < screen_size_y(s); y++) {
|
||||
if (y + yoff >= wsy)
|
||||
continue;
|
||||
cl = &ctx->s->write_list[y];
|
||||
|
||||
r = screen_redraw_get_visible_ranges(wp, 0, y + yoff, wsx,
|
||||
NULL);
|
||||
|
||||
last = UINT_MAX;
|
||||
TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
|
||||
log_debug("collect list: x=%u (last %u), y=%u, used=%u",
|
||||
@@ -1862,27 +2080,57 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
|
||||
fatalx("collect list not in order: %u <= %u",
|
||||
ci->x, last);
|
||||
}
|
||||
screen_write_set_cursor(ctx, ci->x, y);
|
||||
if (ci->type == CLEAR) {
|
||||
screen_write_initctx(ctx, &ttyctx, 1);
|
||||
ttyctx.bg = ci->bg;
|
||||
ttyctx.num = ci->used;
|
||||
tty_write(tty_cmd_clearcharacter, &ttyctx);
|
||||
} else {
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
ttyctx.cell = &ci->gc;
|
||||
ttyctx.wrapped = ci->wrapped;
|
||||
ttyctx.ptr = cl->data + ci->x;
|
||||
ttyctx.num = ci->used;
|
||||
tty_write(tty_cmd_cells, &ttyctx);
|
||||
}
|
||||
items++;
|
||||
wr_length = 0;
|
||||
for (i = 0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx == 0) continue;
|
||||
r_start = ri->px;
|
||||
r_end = ri->px + ri->nx;
|
||||
ci_start = ci->x;
|
||||
ci_end = ci->x + ci->used;
|
||||
|
||||
TAILQ_REMOVE(&cl->items, ci, entry);
|
||||
screen_write_free_citem(ci);
|
||||
last = ci->x;
|
||||
if (ci_start + xoff > r_end ||
|
||||
ci_end + xoff < r_start)
|
||||
continue;
|
||||
|
||||
if (r_start > ci_start + xoff)
|
||||
wr_start = ci_start +
|
||||
(r_start - (ci_start + xoff));
|
||||
else
|
||||
wr_start = ci_start;
|
||||
if (ci_end + xoff > r_end)
|
||||
wr_end = ci_end -
|
||||
((ci_end + xoff) - r_end);
|
||||
else
|
||||
wr_end = ci_end;
|
||||
wr_length = wr_end - wr_start;
|
||||
|
||||
if (wr_length <= 0)
|
||||
continue;
|
||||
screen_write_set_cursor(ctx, wr_start, y);
|
||||
if (ci->type == CLEAR) {
|
||||
screen_write_initctx(ctx, &ttyctx, 1);
|
||||
ttyctx.bg = ci->bg;
|
||||
ttyctx.num = wr_length;
|
||||
tty_write(tty_cmd_clearcharacter,
|
||||
&ttyctx);
|
||||
} else {
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
ttyctx.cell = &ci->gc;
|
||||
ttyctx.wrapped = ci->wrapped;
|
||||
ttyctx.ptr = cl->data + wr_start;
|
||||
ttyctx.num = wr_length;
|
||||
tty_write(tty_cmd_cells, &ttyctx);
|
||||
}
|
||||
items++;
|
||||
|
||||
TAILQ_REMOVE(&cl->items, ci, entry);
|
||||
screen_write_free_citem(ci);
|
||||
last = ci->x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s->cx = cx; s->cy = cy;
|
||||
|
||||
log_debug("%s: flushed %u items (%s)", __func__, items, from);
|
||||
@@ -1957,7 +2205,7 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
if (image_check_area(s, s->cx, s->cy, ci->used, 1) && ctx->wp != NULL)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
@@ -2047,6 +2295,7 @@ void
|
||||
screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct window_pane *wp = ctx->wp;
|
||||
struct grid *gd = s->grid;
|
||||
const struct utf8_data *ud = &gc->data;
|
||||
struct grid_line *gl;
|
||||
@@ -2054,8 +2303,10 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
struct grid_cell tmp_gc, now_gc;
|
||||
struct tty_ctx ttyctx;
|
||||
u_int sx = screen_size_x(s), sy = screen_size_y(s);
|
||||
u_int width = ud->width, xx, not_wrap;
|
||||
int selected, skip = 1, redraw = 0;
|
||||
u_int width = ud->width, xx, not_wrap, i, n, vis;
|
||||
int selected, skip = 1, redraw = 0, yoff = 0;
|
||||
struct visible_ranges *r;
|
||||
struct visible_range *ri;
|
||||
|
||||
/* Ignore padding cells. */
|
||||
if (gc->flags & GRID_FLAG_PADDING)
|
||||
@@ -2153,6 +2404,11 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
if (selected)
|
||||
skip = 0;
|
||||
|
||||
if (wp != NULL)
|
||||
yoff = wp->yoff;
|
||||
r = screen_redraw_get_visible_ranges(wp, s->cx, s->cy + yoff, width,
|
||||
NULL);
|
||||
|
||||
/*
|
||||
* Move the cursor. If not wrapping, stick at the last character and
|
||||
* replace it.
|
||||
@@ -2174,11 +2430,30 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
if (!skip && !(s->mode & MODE_SYNC)) {
|
||||
if (selected) {
|
||||
screen_select_cell(s, &tmp_gc, gc);
|
||||
ttyctx.cell = &tmp_gc;
|
||||
} else
|
||||
ttyctx.cell = gc;
|
||||
memcpy(&tmp_gc, gc, sizeof tmp_gc);
|
||||
ttyctx.cell = &tmp_gc;
|
||||
ttyctx.num = redraw ? 2 : 0;
|
||||
tty_write(tty_cmd_cell, &ttyctx);
|
||||
for (i=0, vis=0; i < r->used; i++) vis += r->ranges[i].nx;
|
||||
if (vis < width) {
|
||||
/* Wide character or tab partly obscured. Write
|
||||
* spaces one by one in unobscured region(s).
|
||||
*/
|
||||
*tmp_gc.data.data = ' ';
|
||||
tmp_gc.data.width = tmp_gc.data.size =
|
||||
tmp_gc.data.have = 1;
|
||||
for (i=0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx == 0) continue;
|
||||
for (n = 0; n < ri->nx; n++) {
|
||||
screen_write_set_cursor(ctx, ri->px + n,
|
||||
-1);
|
||||
tty_write(tty_cmd_cell, &ttyctx);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tty_write(tty_cmd_cell, &ttyctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2187,12 +2462,14 @@ static int
|
||||
screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct window_pane *wp = ctx->wp;
|
||||
struct grid *gd = s->grid;
|
||||
const struct utf8_data *ud = &gc->data;
|
||||
u_int n, cx = s->cx, cy = s->cy;
|
||||
u_int i, n, cx = s->cx, cy = s->cy, vis, yoff = 0;
|
||||
struct grid_cell last;
|
||||
struct tty_ctx ttyctx;
|
||||
int force_wide = 0, zero_width = 0;
|
||||
struct visible_ranges *r;
|
||||
|
||||
/* Ignore U+3164 HANGUL_FILLER entirely. */
|
||||
if (utf8_is_hangul_filler(ud))
|
||||
@@ -2280,6 +2557,23 @@ screen_write_combine(struct screen_write_ctx *ctx, const struct grid_cell *gc)
|
||||
if (force_wide)
|
||||
grid_view_set_padding(gd, cx - 1, cy);
|
||||
|
||||
/*
|
||||
* Check if all of this character is visible. No character will
|
||||
* be obscured in the middle, only on left or right, but there
|
||||
* could be an empty range in the visible ranges so we add them all up.
|
||||
*/
|
||||
if (wp != NULL)
|
||||
yoff = wp->yoff;
|
||||
r = screen_redraw_get_visible_ranges(wp, cx - n, cy + yoff, n, NULL);
|
||||
for (i=0, vis=0; i < r->used; i++) vis += r->ranges[i].nx;
|
||||
if (vis < n) {
|
||||
/*
|
||||
* Part of this character is obscured. Return 1
|
||||
* and let screen_write_cell write a space.
|
||||
*/
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Redraw the combined cell. If forcing the cell to width 2, reset the
|
||||
* cached cursor position in the tty, since we don't really know
|
||||
@@ -2398,7 +2692,7 @@ screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len,
|
||||
tty_write(tty_cmd_rawstring, &ttyctx);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
/* Write a SIXEL image. */
|
||||
void
|
||||
screen_write_sixelimage(struct screen_write_ctx *ctx, struct sixel_image *si,
|
||||
@@ -2450,7 +2744,7 @@ screen_write_sixelimage(struct screen_write_ctx *ctx, struct sixel_image *si,
|
||||
screen_write_collect_flush(ctx, 0, __func__);
|
||||
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
ttyctx.ptr = image_store(s, IMAGE_SIXEL, si);
|
||||
ttyctx.ptr = image_store(s, si);
|
||||
|
||||
tty_write(tty_cmd_sixelimage, &ttyctx);
|
||||
|
||||
@@ -2458,38 +2752,6 @@ screen_write_sixelimage(struct screen_write_ctx *ctx, struct sixel_image *si,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
void
|
||||
screen_write_kittyimage(struct screen_write_ctx *ctx, struct kitty_image *ki)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
struct tty_ctx ttyctx;
|
||||
struct image *im;
|
||||
|
||||
if (ki == NULL)
|
||||
return;
|
||||
|
||||
/* Store the image in the cache. */
|
||||
im = image_store(s, IMAGE_KITTY, ki);
|
||||
|
||||
/* Trigger a tty write to send to all terminals. */
|
||||
if (im != NULL && ctx->wp != NULL) {
|
||||
screen_write_collect_flush(ctx, 0, __func__);
|
||||
screen_write_initctx(ctx, &ttyctx, 0);
|
||||
ttyctx.ptr = im;
|
||||
ttyctx.arg = ctx->wp;
|
||||
ttyctx.ocx = s->cx;
|
||||
ttyctx.ocy = s->cy;
|
||||
ttyctx.set_client_cb = tty_set_client_cb;
|
||||
tty_write(tty_cmd_kittyimage, &ttyctx);
|
||||
}
|
||||
|
||||
/* Move cursor past the image. */
|
||||
if (kitty_get_rows(ki) > 0)
|
||||
screen_write_cursormove(ctx, 0, s->cy + kitty_get_rows(ki), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Turn alternate screen on. */
|
||||
void
|
||||
screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc,
|
||||
|
||||
12
screen.c
12
screen.c
@@ -89,7 +89,7 @@ screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
|
||||
s->tabs = NULL;
|
||||
s->sel = NULL;
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
TAILQ_INIT(&s->images);
|
||||
TAILQ_INIT(&s->saved_images);
|
||||
#endif
|
||||
@@ -127,7 +127,7 @@ screen_reinit(struct screen *s)
|
||||
screen_clear_selection(s);
|
||||
screen_free_titles(s);
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
image_free_all(s);
|
||||
#endif
|
||||
|
||||
@@ -164,7 +164,7 @@ screen_free(struct screen *s)
|
||||
hyperlinks_free(s->hyperlinks);
|
||||
screen_free_titles(s);
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
image_free_all(s);
|
||||
#endif
|
||||
}
|
||||
@@ -324,7 +324,7 @@ screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow,
|
||||
if (sy != screen_size_y(s))
|
||||
screen_resize_y(s, sy, eat_empty, &cy);
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
image_free_all(s);
|
||||
#endif
|
||||
|
||||
@@ -649,7 +649,7 @@ screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
|
||||
}
|
||||
memcpy(&s->saved_cell, gc, sizeof s->saved_cell);
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
TAILQ_CONCAT(&s->saved_images, &s->images, entry);
|
||||
#endif
|
||||
|
||||
@@ -707,7 +707,7 @@ screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
|
||||
grid_destroy(s->saved_grid);
|
||||
s->saved_grid = NULL;
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
image_free_all(s);
|
||||
TAILQ_CONCAT(&s->images, &s->saved_images, entry);
|
||||
#endif
|
||||
|
||||
@@ -617,7 +617,8 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
|
||||
struct options *wo = w->options;
|
||||
struct window_pane *fwp;
|
||||
int pane_status, sb, sb_pos, sb_w, sb_pad;
|
||||
u_int line, sl_top, sl_bottom;
|
||||
u_int pane_status_line, sl_top, sl_bottom;
|
||||
u_int bdr_bottom, bdr_top, bdr_left, bdr_right;
|
||||
|
||||
sb = options_get_number(wo, "pane-scrollbars");
|
||||
sb_pos = options_get_number(wo, "pane-scrollbars-position");
|
||||
@@ -630,16 +631,19 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
|
||||
sb_w = 0;
|
||||
sb_pad = 0;
|
||||
}
|
||||
|
||||
if (pane_status == PANE_STATUS_TOP)
|
||||
line = wp->yoff - 1;
|
||||
pane_status_line = wp->yoff - 1;
|
||||
else if (pane_status == PANE_STATUS_BOTTOM)
|
||||
line = wp->yoff + wp->sy;
|
||||
pane_status_line = wp->yoff + wp->sy;
|
||||
else
|
||||
pane_status_line = -1; /* not used */
|
||||
|
||||
/* Check if point is within the pane or scrollbar. */
|
||||
if (((pane_status != PANE_STATUS_OFF &&
|
||||
py != line && py != wp->yoff + wp->sy) ||
|
||||
py != pane_status_line && py != wp->yoff + wp->sy) ||
|
||||
(wp->yoff == 0 && py < wp->sy) ||
|
||||
(py >= wp->yoff && py < wp->yoff + wp->sy)) &&
|
||||
((int)py >= wp->yoff && py < wp->yoff + wp->sy)) &&
|
||||
((sb_pos == PANE_SCROLLBARS_RIGHT &&
|
||||
px < wp->xoff + wp->sx + sb_pad + sb_w) ||
|
||||
(sb_pos == PANE_SCROLLBARS_LEFT &&
|
||||
@@ -649,8 +653,8 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
|
||||
(px >= wp->xoff + wp->sx + sb_pad &&
|
||||
px < wp->xoff + wp->sx + sb_pad + sb_w)) ||
|
||||
(sb_pos == PANE_SCROLLBARS_LEFT &&
|
||||
(px >= wp->xoff - sb_pad - sb_w &&
|
||||
px < wp->xoff - sb_pad))) {
|
||||
((int)px >= wp->xoff - sb_pad - sb_w &&
|
||||
(int)px < wp->xoff - sb_pad))) {
|
||||
/* Check where inside the scrollbar. */
|
||||
sl_top = wp->yoff + wp->sb_slider_y;
|
||||
sl_bottom = (wp->yoff + wp->sb_slider_y +
|
||||
@@ -663,6 +667,12 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
|
||||
return (SCROLLBAR_SLIDER);
|
||||
} else /* py > sl_bottom */
|
||||
return (SCROLLBAR_DOWN);
|
||||
} else if (wp->flags & PANE_FLOATING &&
|
||||
((int)px == wp->xoff - 1 ||
|
||||
(int)py == wp->yoff - 1 ||
|
||||
(int)py == wp->yoff + (int)wp->sy)) {
|
||||
/* Floating pane left, bottom or top border. */
|
||||
return (BORDER);
|
||||
} else {
|
||||
/* Must be inside the pane. */
|
||||
return (PANE);
|
||||
@@ -670,16 +680,32 @@ server_client_check_mouse_in_pane(struct window_pane *wp, u_int px, u_int py,
|
||||
} else if (~w->flags & WINDOW_ZOOMED) {
|
||||
/* Try the pane borders if not zoomed. */
|
||||
TAILQ_FOREACH(fwp, &w->panes, entry) {
|
||||
if ((((sb_pos == PANE_SCROLLBARS_RIGHT &&
|
||||
fwp->xoff + fwp->sx + sb_pad + sb_w == px) ||
|
||||
(sb_pos == PANE_SCROLLBARS_LEFT &&
|
||||
fwp->xoff + fwp->sx == px)) &&
|
||||
fwp->yoff <= 1 + py &&
|
||||
fwp->yoff + fwp->sy >= py) ||
|
||||
(fwp->yoff + fwp->sy == py &&
|
||||
fwp->xoff <= 1 + px &&
|
||||
fwp->xoff + fwp->sx >= px))
|
||||
break;
|
||||
if (sb_pos == PANE_SCROLLBARS_LEFT)
|
||||
bdr_right = fwp->xoff + fwp->sx;
|
||||
else
|
||||
/* PANE_SCROLLBARS_RIGHT or none. */
|
||||
bdr_right = fwp->xoff + fwp->sx + sb_pad + sb_w;
|
||||
if ((int)py >= fwp->yoff - 1 && py <= fwp->yoff + fwp->sy) {
|
||||
if (px == bdr_right)
|
||||
break;
|
||||
if (wp->flags & PANE_FLOATING) {
|
||||
/* Floating pane, check if left border. */
|
||||
bdr_left = fwp->xoff - 1;
|
||||
if (px == bdr_left)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((int)px >= fwp->xoff - 1 && px <= fwp->xoff + fwp->sx) {
|
||||
bdr_bottom = fwp->yoff + fwp->sy;
|
||||
if (py == bdr_bottom)
|
||||
break;
|
||||
if (wp->flags & PANE_FLOATING) {
|
||||
/* Floating pane, check if top border. */
|
||||
bdr_top = fwp->yoff - 1;
|
||||
if (py == bdr_top)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fwp != NULL)
|
||||
return (BORDER);
|
||||
@@ -849,9 +875,11 @@ have_event:
|
||||
* scrollbar.
|
||||
*/
|
||||
if (where == NOWHERE) {
|
||||
if (c->tty.mouse_scrolling_flag)
|
||||
if (c->tty.mouse_scrolling_flag) {
|
||||
where = SCROLLBAR_SLIDER;
|
||||
else {
|
||||
m->wp = c->tty.mouse_wp->id;
|
||||
m->w = c->tty.mouse_wp->window->id;
|
||||
} else {
|
||||
px = x;
|
||||
if (m->statusat == 0 && y >= m->statuslines)
|
||||
py = y - m->statuslines;
|
||||
@@ -868,8 +896,13 @@ have_event:
|
||||
px = px + m->ox;
|
||||
py = py + m->oy;
|
||||
|
||||
/* Try inside the pane. */
|
||||
wp = window_get_active_at(w, px, py);
|
||||
if (type == DRAG &&
|
||||
c->tty.mouse_wp != NULL)
|
||||
/* Use pane from last mouse event. */
|
||||
wp = c->tty.mouse_wp;
|
||||
else
|
||||
/* Try inside the pane. */
|
||||
wp = window_get_active_at(w, px, py);
|
||||
if (wp == NULL)
|
||||
return (KEYC_UNKNOWN);
|
||||
where = server_client_check_mouse_in_pane(wp, px, py,
|
||||
@@ -1086,6 +1119,7 @@ have_event:
|
||||
break;
|
||||
}
|
||||
c->tty.mouse_drag_flag = 0;
|
||||
c->tty.mouse_wp = NULL;
|
||||
c->tty.mouse_slider_mpos = -1;
|
||||
goto out;
|
||||
}
|
||||
@@ -1101,6 +1135,7 @@ have_event:
|
||||
if (wp != NULL &&
|
||||
wp != w->active &&
|
||||
options_get_number(s->options, "focus-follows-mouse")) {
|
||||
window_redraw_active_switch(w, wp);
|
||||
window_set_active_pane(w, wp, 1);
|
||||
server_redraw_window_borders(w);
|
||||
server_status_window(w);
|
||||
@@ -1312,6 +1347,11 @@ have_event:
|
||||
* where the user grabbed.
|
||||
*/
|
||||
c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1;
|
||||
/* Only change pane if not already dragging a pane border. */
|
||||
if (c->tty.mouse_wp == NULL) {
|
||||
wp = window_get_active_at(w, px, py);
|
||||
c->tty.mouse_wp = wp;
|
||||
}
|
||||
if (c->tty.mouse_scrolling_flag == 0 &&
|
||||
where == SCROLLBAR_SLIDER) {
|
||||
c->tty.mouse_scrolling_flag = 1;
|
||||
@@ -2980,7 +3020,7 @@ server_client_reset_state(struct client *c)
|
||||
if (c->overlay_draw != NULL) {
|
||||
if (c->overlay_mode != NULL)
|
||||
s = c->overlay_mode(c, c->overlay_data, &cx, &cy);
|
||||
} else if (c->prompt_string == NULL)
|
||||
} else if (wp != NULL && c->prompt_string == NULL)
|
||||
s = wp->screen;
|
||||
else
|
||||
s = c->status.active;
|
||||
@@ -3008,7 +3048,7 @@ server_client_reset_state(struct client *c)
|
||||
cy = tty->sy - 1;
|
||||
}
|
||||
cx = c->prompt_cursor;
|
||||
} else if (c->overlay_draw == NULL) {
|
||||
} else if (wp != NULL && c->overlay_draw == NULL) {
|
||||
cursor = 0;
|
||||
tty_window_offset(tty, &ox, &oy, &sx, &sy);
|
||||
if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx &&
|
||||
@@ -3021,9 +3061,15 @@ server_client_reset_state(struct client *c)
|
||||
if (status_at_line(c) == 0)
|
||||
cy += status_line_size(c);
|
||||
}
|
||||
if (!screen_redraw_is_visible(
|
||||
screen_redraw_get_visible_ranges(wp, cx, cy, 1, NULL), cx))
|
||||
cursor = 0;
|
||||
|
||||
if (!cursor)
|
||||
mode &= ~MODE_CURSOR;
|
||||
}
|
||||
} else
|
||||
mode &= ~MODE_CURSOR;
|
||||
|
||||
log_debug("%s: cursor to %u,%u", __func__, cx, cy);
|
||||
tty_cursor(tty, cx, cy);
|
||||
|
||||
@@ -3708,7 +3754,7 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
||||
c->term_name = xstrdup("unknown");
|
||||
}
|
||||
|
||||
if (c->ttyname == NULL || *c->ttyname != '\0')
|
||||
if (c->ttyname != NULL && *c->ttyname != '\0')
|
||||
name = xstrdup(c->ttyname);
|
||||
else
|
||||
xasprintf(&name, "client-%ld", (long)c->pid);
|
||||
|
||||
7
spawn.c
7
spawn.c
@@ -276,6 +276,13 @@ spawn_pane(struct spawn_context *sc, char **cause)
|
||||
layout_assign_pane(sc->lc, new_wp, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If window currently zoomed, window_set_active_pane calls
|
||||
* window_unzoom which it copies back the saved_layout_cell.
|
||||
*/
|
||||
if (w->flags & WINDOW_ZOOMED)
|
||||
new_wp->saved_layout_cell = new_wp->layout_cell;
|
||||
|
||||
/*
|
||||
* Now we have a pane with nothing running in it ready for the new
|
||||
* process. Work out the command and arguments and store the working
|
||||
|
||||
3
tmux.1
3
tmux.1
@@ -6266,7 +6266,6 @@ The following variables are available, where appropriate:
|
||||
.It Li "hook_window_name" Ta "" Ta "Name of window where hook was run, if any"
|
||||
.It Li "host" Ta "#H" Ta "Hostname of local host"
|
||||
.It Li "host_short" Ta "#h" Ta "Hostname of local host (no domain name)"
|
||||
.It Li "image_support" Ta "" Ta "Returns the string of the support image (sixel, kitty)"
|
||||
.It Li "insert_flag" Ta "" Ta "Pane insert flag"
|
||||
.It Li "key_string" Ta "" Ta "String representation of the key binding"
|
||||
.It Li "key_repeat" Ta "" Ta "1 if key binding is repeatable"
|
||||
@@ -6311,6 +6310,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "pane_dead_status" Ta "" Ta "Exit status of process in dead pane"
|
||||
.It Li "pane_dead_time" Ta "" Ta "Exit time of process in dead pane"
|
||||
.It Li "pane_fg" Ta "" Ta "Pane foreground colour"
|
||||
.It Li "pane_floating_flag" Ta "" Ta "1 if pane is floating"
|
||||
.It Li "pane_format" Ta "" Ta "1 if format is for a pane"
|
||||
.It Li "pane_height" Ta "" Ta "Height of pane"
|
||||
.It Li "pane_id" Ta "#D" Ta "Unique pane ID"
|
||||
@@ -6381,6 +6381,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "session_stack" Ta "" Ta "Window indexes in most recent order"
|
||||
.It Li "session_windows" Ta "" Ta "Number of windows in session"
|
||||
.It Li "socket_path" Ta "" Ta "Server socket path"
|
||||
.It Li "sixel_support" Ta "" Ta "1 if server has support for SIXEL"
|
||||
.It Li "start_time" Ta "" Ta "Server start time"
|
||||
.It Li "synchronized_output_flag" Ta "" Ta "1 if pane has synchronized output enabled"
|
||||
.It Li "uid" Ta "" Ta "Server UID"
|
||||
|
||||
144
tmux.h
144
tmux.h
@@ -68,19 +68,10 @@ struct screen_write_cline;
|
||||
struct screen_write_ctx;
|
||||
struct session;
|
||||
|
||||
/* Convenience macro: defined if any image protocol is compiled in. */
|
||||
#if defined(ENABLE_SIXEL_IMAGES) || defined(ENABLE_KITTY_IMAGES)
|
||||
#define ENABLE_IMAGES
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
struct sixel_image;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
struct kitty_image;
|
||||
#endif
|
||||
|
||||
struct tty_ctx;
|
||||
struct tty_code;
|
||||
struct tty_key;
|
||||
@@ -934,25 +925,11 @@ struct style {
|
||||
enum style_default_type default_type;
|
||||
};
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
/* Image types. */
|
||||
enum image_type {
|
||||
IMAGE_SIXEL,
|
||||
IMAGE_KITTY
|
||||
};
|
||||
|
||||
#ifdef ENABLE_SIXEL
|
||||
/* Image. */
|
||||
struct image {
|
||||
enum image_type type;
|
||||
struct screen *s;
|
||||
union {
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
struct sixel_image *sixel;
|
||||
#endif
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
struct kitty_image *kitty;
|
||||
#endif
|
||||
} data;
|
||||
struct sixel_image *data;
|
||||
char *fallback;
|
||||
|
||||
u_int px;
|
||||
@@ -1007,7 +984,7 @@ struct screen {
|
||||
bitstr_t *tabs;
|
||||
struct screen_sel *sel;
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
struct images images;
|
||||
struct images saved_images;
|
||||
#endif
|
||||
@@ -1086,8 +1063,8 @@ struct screen_redraw_ctx {
|
||||
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
u_int ox;
|
||||
u_int oy;
|
||||
int ox;
|
||||
int oy;
|
||||
};
|
||||
|
||||
/* Screen size. */
|
||||
@@ -1202,6 +1179,19 @@ enum client_theme {
|
||||
THEME_DARK
|
||||
};
|
||||
|
||||
/* Visible range array element. */
|
||||
struct visible_range {
|
||||
u_int px; /* start */
|
||||
u_int nx; /* length */
|
||||
};
|
||||
|
||||
/* Visible areas not obstructed. */
|
||||
struct visible_ranges {
|
||||
struct visible_range *ranges; /* dynamically allocated array */
|
||||
u_int used; /* number of entries in ranges */
|
||||
u_int size; /* allocated capacity of ranges */
|
||||
};
|
||||
|
||||
/* Child window structure. */
|
||||
struct window_pane {
|
||||
u_int id;
|
||||
@@ -1216,10 +1206,11 @@ struct window_pane {
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
|
||||
u_int xoff;
|
||||
u_int yoff;
|
||||
int xoff;
|
||||
int yoff;
|
||||
|
||||
int flags;
|
||||
int saved_flags;
|
||||
#define PANE_REDRAW 0x1
|
||||
#define PANE_DROP 0x2
|
||||
#define PANE_FOCUSED 0x4
|
||||
@@ -1236,6 +1227,8 @@ struct window_pane {
|
||||
#define PANE_THEMECHANGED 0x2000
|
||||
#define PANE_UNSEENCHANGES 0x4000
|
||||
#define PANE_REDRAWSCROLLBAR 0x8000
|
||||
#define PANE_FLOATING 0x10000
|
||||
#define PANE_MINIMISED 0x20000
|
||||
|
||||
u_int sb_slider_y;
|
||||
u_int sb_slider_h;
|
||||
@@ -1291,11 +1284,15 @@ struct window_pane {
|
||||
|
||||
struct style scrollbar_style;
|
||||
|
||||
struct visible_ranges r;
|
||||
|
||||
TAILQ_ENTRY(window_pane) entry; /* link in list of all panes */
|
||||
TAILQ_ENTRY(window_pane) sentry; /* link in list of last visited */
|
||||
TAILQ_ENTRY(window_pane) zentry; /* z-index link in list of all panes */
|
||||
RB_ENTRY(window_pane) tree_entry;
|
||||
};
|
||||
TAILQ_HEAD(window_panes, window_pane);
|
||||
TAILQ_HEAD(window_panes_zindex, window_pane);
|
||||
RB_HEAD(window_pane_tree, window_pane);
|
||||
|
||||
/* Window structure. */
|
||||
@@ -1315,6 +1312,7 @@ struct window {
|
||||
|
||||
struct window_pane *active;
|
||||
struct window_panes last_panes;
|
||||
struct window_panes z_index;
|
||||
struct window_panes panes;
|
||||
|
||||
int lastlayout;
|
||||
@@ -1408,6 +1406,7 @@ TAILQ_HEAD(winlink_stack, winlink);
|
||||
enum layout_type {
|
||||
LAYOUT_LEFTRIGHT,
|
||||
LAYOUT_TOPBOTTOM,
|
||||
LAYOUT_FLOATING,
|
||||
LAYOUT_WINDOWPANE
|
||||
};
|
||||
|
||||
@@ -1559,19 +1558,6 @@ struct key_event {
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/* Visible range array element. */
|
||||
struct visible_range {
|
||||
u_int px; /* start */
|
||||
u_int nx; /* length */
|
||||
};
|
||||
|
||||
/* Visible areas not obstructed. */
|
||||
struct visible_ranges {
|
||||
struct visible_range *ranges; /* dynamically allocated array */
|
||||
u_int used; /* number of entries in ranges */
|
||||
u_int size; /* allocated capacity of ranges */
|
||||
};
|
||||
|
||||
/* Terminal definition. */
|
||||
struct tty_term {
|
||||
char *name;
|
||||
@@ -1589,7 +1575,6 @@ struct tty_term {
|
||||
#define TERM_RGBCOLOURS 0x10
|
||||
#define TERM_VT100LIKE 0x20
|
||||
#define TERM_SIXEL 0x40
|
||||
#define TERM_KITTY 0x80
|
||||
int flags;
|
||||
|
||||
LIST_ENTRY(tty_term) entry;
|
||||
@@ -1672,7 +1657,7 @@ struct tty {
|
||||
int mouse_drag_flag;
|
||||
int mouse_scrolling_flag;
|
||||
int mouse_slider_mpos;
|
||||
|
||||
struct window_pane *mouse_wp;
|
||||
void (*mouse_drag_update)(struct client *,
|
||||
struct mouse_event *);
|
||||
void (*mouse_drag_release)(struct client *,
|
||||
@@ -1718,10 +1703,10 @@ struct tty_ctx {
|
||||
u_int orlower;
|
||||
|
||||
/* Target region (usually pane) offset and size. */
|
||||
u_int xoff;
|
||||
u_int yoff;
|
||||
u_int rxoff;
|
||||
u_int ryoff;
|
||||
int xoff;
|
||||
int yoff;
|
||||
int rxoff;
|
||||
int ryoff;
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
|
||||
@@ -1738,6 +1723,9 @@ struct tty_ctx {
|
||||
u_int woy;
|
||||
u_int wsx;
|
||||
u_int wsy;
|
||||
|
||||
/* tty partly obscured, it will need to be surgically scrolled. */
|
||||
u_int obscured;
|
||||
};
|
||||
|
||||
/* Saved message entry. */
|
||||
@@ -2289,6 +2277,7 @@ struct spawn_context {
|
||||
#define SPAWN_FULLSIZE 0x20
|
||||
#define SPAWN_EMPTY 0x40
|
||||
#define SPAWN_ZOOM 0x80
|
||||
#define SPAWN_FLOATING 0x100
|
||||
};
|
||||
|
||||
/* Paste buffer. */
|
||||
@@ -2644,7 +2633,7 @@ struct visible_ranges *tty_check_overlay_range(struct tty *, u_int, u_int,
|
||||
void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int,
|
||||
u_int, u_int, const struct grid_cell *, struct colour_palette *);
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
void tty_draw_images(struct client *, struct window_pane *, struct screen *);
|
||||
#endif
|
||||
|
||||
@@ -2678,22 +2667,10 @@ void tty_cmd_reverseindex(struct tty *, const struct tty_ctx *);
|
||||
void tty_cmd_setselection(struct tty *, const struct tty_ctx *);
|
||||
void tty_cmd_rawstring(struct tty *, const struct tty_ctx *);
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
int tty_set_client_cb(struct tty_ctx *, struct client *);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
void tty_cmd_sixelimage(struct tty *, const struct tty_ctx *);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
void tty_cmd_kittyimage(struct tty *, const struct tty_ctx *);
|
||||
void tty_kitty_delete_all(struct tty *);
|
||||
void tty_kitty_delete_all_pane(struct window_pane *);
|
||||
void tty_kitty_passthrough(struct window_pane *, const char *, size_t,
|
||||
u_int, u_int);
|
||||
#endif
|
||||
|
||||
void tty_cmd_syncstart(struct tty *, const struct tty_ctx *);
|
||||
void tty_default_colours(struct grid_cell *, struct window_pane *);
|
||||
|
||||
@@ -3296,15 +3273,10 @@ void screen_write_setselection(struct screen_write_ctx *, const char *,
|
||||
u_char *, u_int);
|
||||
void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int,
|
||||
int);
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
void screen_write_sixelimage(struct screen_write_ctx *,
|
||||
struct sixel_image *, u_int);
|
||||
#endif
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
void screen_write_kittyimage(struct screen_write_ctx *,
|
||||
struct kitty_image *);
|
||||
#endif
|
||||
|
||||
void screen_write_alternateon(struct screen_write_ctx *,
|
||||
struct grid_cell *, int);
|
||||
void screen_write_alternateoff(struct screen_write_ctx *,
|
||||
@@ -3313,6 +3285,10 @@ void screen_write_alternateoff(struct screen_write_ctx *,
|
||||
/* screen-redraw.c */
|
||||
void screen_redraw_screen(struct client *);
|
||||
void screen_redraw_pane(struct client *, struct window_pane *, int);
|
||||
int screen_redraw_is_visible(struct visible_ranges *, u_int px);
|
||||
struct visible_ranges *screen_redraw_get_visible_ranges(struct window_pane *,
|
||||
u_int, u_int, u_int, struct visible_ranges *);
|
||||
|
||||
|
||||
/* screen.c */
|
||||
void screen_init(struct screen *, u_int, u_int, u_int);
|
||||
@@ -3375,6 +3351,8 @@ struct window_pane *window_find_string(struct window *, const char *);
|
||||
int window_has_pane(struct window *, struct window_pane *);
|
||||
int window_set_active_pane(struct window *, struct window_pane *,
|
||||
int);
|
||||
int window_deactivate_pane(struct window *, struct window_pane *,
|
||||
int);
|
||||
void window_update_focus(struct window *);
|
||||
void window_pane_update_focus(struct window_pane *);
|
||||
void window_redraw_active_switch(struct window *,
|
||||
@@ -3401,6 +3379,7 @@ struct window_pane *window_pane_find_by_id_str(const char *);
|
||||
struct window_pane *window_pane_find_by_id(u_int);
|
||||
int window_pane_destroy_ready(struct window_pane *);
|
||||
void window_pane_resize(struct window_pane *, u_int, u_int);
|
||||
void window_pane_move(struct window_pane *, int, int);
|
||||
int window_pane_set_mode(struct window_pane *,
|
||||
struct window_pane *, const struct window_mode *,
|
||||
struct cmd_find_state *, struct args *);
|
||||
@@ -3454,6 +3433,8 @@ void layout_free_cell(struct layout_cell *);
|
||||
void layout_print_cell(struct layout_cell *, const char *, u_int);
|
||||
void layout_destroy_cell(struct window *, struct layout_cell *,
|
||||
struct layout_cell **);
|
||||
void layout_minimise_cell(struct window *, struct layout_cell *);
|
||||
void layout_unminimise_cell(struct window *, struct layout_cell *);
|
||||
void layout_resize_layout(struct window *, struct layout_cell *,
|
||||
enum layout_type, int, int);
|
||||
struct layout_cell *layout_search_by_border(struct layout_cell *, u_int, u_int);
|
||||
@@ -3461,6 +3442,7 @@ void layout_set_size(struct layout_cell *, u_int, u_int, u_int,
|
||||
u_int);
|
||||
void layout_make_leaf(struct layout_cell *, struct window_pane *);
|
||||
void layout_make_node(struct layout_cell *, enum layout_type);
|
||||
void layout_fix_zindexes(struct window *, struct layout_cell *);
|
||||
void layout_fix_offsets(struct window *);
|
||||
void layout_fix_panes(struct window *, struct window_pane *);
|
||||
void layout_resize_adjust(struct window *, struct layout_cell *,
|
||||
@@ -3481,7 +3463,7 @@ int layout_spread_cell(struct window *, struct layout_cell *);
|
||||
void layout_spread_out(struct window_pane *);
|
||||
|
||||
/* layout-custom.c */
|
||||
char *layout_dump(struct layout_cell *);
|
||||
char *layout_dump(struct window *, struct layout_cell *);
|
||||
int layout_parse(struct window *, const char *, char **);
|
||||
|
||||
/* layout-set.c */
|
||||
@@ -3555,7 +3537,7 @@ void printflike(3, 4) window_copy_add(struct window_pane *, int, const char *,
|
||||
...);
|
||||
void printflike(3, 0) window_copy_vadd(struct window_pane *, int, const char *,
|
||||
va_list);
|
||||
void window_copy_scroll(struct window_pane *, int, u_int, int);
|
||||
void window_copy_scroll(struct window_pane *, int, u_int, u_int, int);
|
||||
void window_copy_pageup(struct window_pane *, int);
|
||||
void window_copy_pagedown(struct window_pane *, int, int);
|
||||
void window_copy_start_drag(struct client *, struct mouse_event *);
|
||||
@@ -3768,16 +3750,14 @@ struct window_pane *spawn_pane(struct spawn_context *, char **);
|
||||
/* regsub.c */
|
||||
char *regsub(const char *, const char *, const char *, int);
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
/* image.c */
|
||||
int image_free_all(struct screen *);
|
||||
struct image *image_store(struct screen *, enum image_type, void *);
|
||||
struct image *image_store(struct screen *, struct sixel_image *);
|
||||
int image_check_line(struct screen *, u_int, u_int);
|
||||
int image_check_area(struct screen *, u_int, u_int, u_int, u_int);
|
||||
int image_scroll_up(struct screen *, u_int);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
/* image-sixel.c */
|
||||
#define SIXEL_COLOUR_REGISTERS 1024
|
||||
struct sixel_image *sixel_parse(const char *, size_t, u_int, u_int, u_int);
|
||||
@@ -3791,18 +3771,6 @@ char *sixel_print(struct sixel_image *, struct sixel_image *,
|
||||
struct screen *sixel_to_screen(struct sixel_image *);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
/* image-kitty.c */
|
||||
struct kitty_image *kitty_parse(const u_char *, size_t, u_int, u_int);
|
||||
void kitty_free(struct kitty_image *);
|
||||
void kitty_size_in_cells(struct kitty_image *, u_int *, u_int *);
|
||||
char kitty_get_action(struct kitty_image *);
|
||||
u_int kitty_get_image_id(struct kitty_image *);
|
||||
u_int kitty_get_rows(struct kitty_image *);
|
||||
char *kitty_print(struct kitty_image *, size_t *);
|
||||
char *kitty_delete_all(size_t *);
|
||||
#endif
|
||||
|
||||
/* server-acl.c */
|
||||
void server_acl_init(void);
|
||||
struct server_acl_user *server_acl_user_find(uid_t);
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 172 KiB |
@@ -122,7 +122,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
char buf[1000];
|
||||
size_t len;
|
||||
enum tty_draw_line_state current_state, next_state;
|
||||
|
||||
/* xxx maybe check overlay here? */
|
||||
/*
|
||||
* py is the line in the screen to draw. px is the start x and nx is
|
||||
* the width to draw. atx,aty is the line on the terminal to draw it.
|
||||
|
||||
@@ -357,17 +357,6 @@ static const struct tty_feature tty_feature_sixel = {
|
||||
TERM_SIXEL
|
||||
};
|
||||
|
||||
/* Terminal has kitty graphics protocol capability. */
|
||||
static const char *const tty_feature_kitty_capabilities[] = {
|
||||
"Kty",
|
||||
NULL
|
||||
};
|
||||
static const struct tty_feature tty_feature_kitty = {
|
||||
"kitty",
|
||||
tty_feature_kitty_capabilities,
|
||||
TERM_KITTY
|
||||
};
|
||||
|
||||
/* Available terminal features. */
|
||||
static const struct tty_feature *const tty_features[] = {
|
||||
&tty_feature_256,
|
||||
@@ -379,7 +368,6 @@ static const struct tty_feature *const tty_features[] = {
|
||||
&tty_feature_extkeys,
|
||||
&tty_feature_focus,
|
||||
&tty_feature_ignorefkeys,
|
||||
&tty_feature_kitty,
|
||||
&tty_feature_margins,
|
||||
&tty_feature_mouse,
|
||||
&tty_feature_osc7,
|
||||
@@ -512,19 +500,7 @@ tty_default_features(int *feat, const char *name, u_int version)
|
||||
*/
|
||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
||||
",ccolour,cstyle,extkeys,focus"
|
||||
},
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
{ .name = "kitty",
|
||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
||||
",ccolour,cstyle,extkeys,focus,sync,hyperlinks"
|
||||
",kitty"
|
||||
},
|
||||
{ .name = "ghostty",
|
||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
||||
",ccolour,cstyle,extkeys,focus,sync,hyperlinks"
|
||||
",kitty"
|
||||
},
|
||||
#endif
|
||||
}
|
||||
};
|
||||
u_int i;
|
||||
|
||||
|
||||
96
tty-keys.c
96
tty-keys.c
@@ -60,10 +60,6 @@ static int tty_keys_device_attributes2(struct tty *, const char *, size_t,
|
||||
static int tty_keys_extended_device_attributes(struct tty *, const char *,
|
||||
size_t, size_t *);
|
||||
static int tty_keys_palette(struct tty *, const char *, size_t, size_t *);
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
static int tty_keys_kitty_graphics(struct tty *, const char *, size_t,
|
||||
size_t *);
|
||||
#endif
|
||||
|
||||
/* A key tree entry. */
|
||||
struct tty_key {
|
||||
@@ -763,19 +759,6 @@ tty_keys_next(struct tty *tty)
|
||||
goto partial_key;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
/* Is this a kitty graphics protocol response? ESC _ G ... ESC \ */
|
||||
switch (tty_keys_kitty_graphics(tty, buf, len, &size)) {
|
||||
case 0: /* yes */
|
||||
key = KEYC_UNKNOWN;
|
||||
goto complete_key;
|
||||
case -1: /* no, or not valid */
|
||||
break;
|
||||
case 1: /* partial */
|
||||
goto partial_key;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Is this a primary device attributes response? */
|
||||
switch (tty_keys_device_attributes(tty, buf, len, &size)) {
|
||||
case 0: /* yes */
|
||||
@@ -1657,14 +1640,6 @@ tty_keys_extended_device_attributes(struct tty *tty, const char *buf,
|
||||
tty_default_features(features, "mintty", 0);
|
||||
else if (strncmp(tmp, "foot(", 5) == 0)
|
||||
tty_default_features(features, "foot", 0);
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
else if (strncmp(tmp, "kitty ", 6) == 0 ||
|
||||
strcmp(tmp, "kitty") == 0)
|
||||
tty_default_features(features, "kitty", 0);
|
||||
else if (strncmp(tmp, "ghostty ", 8) == 0 ||
|
||||
strcmp(tmp, "ghostty") == 0)
|
||||
tty_default_features(features, "ghostty", 0);
|
||||
#endif
|
||||
log_debug("%s: received extended DA %.*s", c->name, (int)*size, buf);
|
||||
|
||||
free(c->term_type);
|
||||
@@ -1820,74 +1795,3 @@ tty_keys_palette(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
/*
|
||||
* Handle kitty graphics protocol response from outer terminal.
|
||||
* Format: ESC _ G <key=value,...> ; <message> ESC \
|
||||
* The response to our capability probe (a=q) is:
|
||||
* ESC _ G i=31;OK ESC \ (supported)
|
||||
* ESC _ G i=31;ENOSYS:... (not supported)
|
||||
* Returns 0 for success, -1 for not a kitty response, 1 for partial.
|
||||
*/
|
||||
static int
|
||||
tty_keys_kitty_graphics(struct tty *tty, const char *buf, size_t len,
|
||||
size_t *size)
|
||||
{
|
||||
struct client *c = tty->client;
|
||||
int *features = &c->term_features;
|
||||
const char *semi;
|
||||
size_t i;
|
||||
char tmp[256];
|
||||
|
||||
*size = 0;
|
||||
|
||||
/*
|
||||
* Kitty APC response starts with ESC _ G (3 bytes).
|
||||
* The 8-bit C1 equivalent 0x9f could also be used but is rare.
|
||||
*/
|
||||
if (buf[0] != '\033')
|
||||
return (-1);
|
||||
if (len == 1)
|
||||
return (1);
|
||||
if (buf[1] != '_')
|
||||
return (-1);
|
||||
if (len == 2)
|
||||
return (1);
|
||||
if (buf[2] != 'G')
|
||||
return (-1);
|
||||
if (len == 3)
|
||||
return (1);
|
||||
|
||||
/* Collect body up to ESC \ (ST). */
|
||||
for (i = 0; i < sizeof(tmp) - 1; i++) {
|
||||
if (3 + i + 1 >= len)
|
||||
return (1); /* partial */
|
||||
if (buf[3 + i] == '\033' && buf[3 + i + 1] == '\\') {
|
||||
tmp[i] = '\0';
|
||||
*size = 3 + i + 2;
|
||||
break;
|
||||
}
|
||||
tmp[i] = buf[3 + i];
|
||||
}
|
||||
if (i == sizeof(tmp) - 1)
|
||||
return (-1); /* too long, not a valid response */
|
||||
|
||||
log_debug("%s: kitty graphics response: %s", c->name, tmp);
|
||||
|
||||
/*
|
||||
* Check if the message (after the semicolon) starts with "OK".
|
||||
* The format is: i=31;OK or i=31;ENOSYS:...
|
||||
*/
|
||||
semi = strchr(tmp, ';');
|
||||
if (semi != NULL && strncmp(semi + 1, "OK", 2) == 0) {
|
||||
log_debug("%s: kitty graphics supported", c->name);
|
||||
tty_add_features(features, "kitty", ",");
|
||||
tty_update_features(tty);
|
||||
} else {
|
||||
log_debug("%s: kitty graphics not supported", c->name);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -461,9 +461,6 @@ tty_term_apply_overrides(struct tty_term *term)
|
||||
/* Log the SIXEL flag. */
|
||||
log_debug("SIXEL flag is %d", !!(term->flags & TERM_SIXEL));
|
||||
|
||||
/* Log the KITTY flag. */
|
||||
log_debug("KITTY flag is %d", !!(term->flags & TERM_KITTY));
|
||||
|
||||
/* Update the RGB flag if the terminal has RGB colours. */
|
||||
if (tty_term_has(term, TTYC_SETRGBF) &&
|
||||
tty_term_has(term, TTYC_SETRGBB))
|
||||
|
||||
343
tty.c
343
tty.c
@@ -67,7 +67,7 @@ static void tty_emulate_repeat(struct tty *, enum tty_code_code,
|
||||
static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int);
|
||||
static int tty_check_overlay(struct tty *, u_int, u_int);
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
static void tty_write_one(void (*)(struct tty *, const struct tty_ctx *),
|
||||
struct client *, struct tty_ctx *);
|
||||
#endif
|
||||
@@ -391,23 +391,6 @@ tty_send_requests(struct tty *tty)
|
||||
return;
|
||||
|
||||
if (tty->term->flags & TERM_VT100LIKE) {
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
/*
|
||||
* Send the kitty graphics capability probe BEFORE the DA1
|
||||
* request. Per the kitty spec, a supporting terminal sends
|
||||
* its APC response before processing any subsequent requests.
|
||||
* So the reply ordering will be:
|
||||
* 1. ESC _ G i=31;OK ESC \ (kitty response, if supported)
|
||||
* 2. ESC [ ? ... c (DA1 response)
|
||||
* 3. ESC [ > ... c (DA2 response)
|
||||
* 4. ESC P > | ... ESC \ (XDA response)
|
||||
* which is exactly what our parsers expect.
|
||||
* Only probe if the kitty feature isn't already enabled.
|
||||
*/
|
||||
if (~tty->term->flags & TERM_KITTY)
|
||||
tty_puts(tty,
|
||||
"\033_Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\033\\");
|
||||
#endif
|
||||
if (~tty->flags & TTY_HAVEDA)
|
||||
tty_puts(tty, "\033[c");
|
||||
if (~tty->flags & TTY_HAVEDA2)
|
||||
@@ -1020,7 +1003,10 @@ tty_window_offset1(struct tty *tty, u_int *ox, u_int *oy, u_int *sx, u_int *sy)
|
||||
else if (cy > w->sy - *sy)
|
||||
*oy = w->sy - *sy;
|
||||
else
|
||||
*oy = cy - *sy / 2;
|
||||
/* cy-sy/2 was causing panned panes to scroll
|
||||
* when the cursor was half way down the pane.
|
||||
*/
|
||||
*oy = cy - *sy + 1; /* cy - *sy / 2; */
|
||||
}
|
||||
|
||||
c->pan_window = NULL;
|
||||
@@ -1140,23 +1126,23 @@ static int
|
||||
tty_clamp_line(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
|
||||
u_int nx, u_int *i, u_int *x, u_int *rx, u_int *ry)
|
||||
{
|
||||
u_int xoff = ctx->rxoff + px;
|
||||
int xoff = ctx->rxoff + px;
|
||||
|
||||
if (!tty_is_visible(tty, ctx, px, py, nx, 1))
|
||||
return (0);
|
||||
*ry = ctx->yoff + py - ctx->woy;
|
||||
|
||||
if (xoff >= ctx->wox && xoff + nx <= ctx->wox + ctx->wsx) {
|
||||
if (xoff >= (int)ctx->wox && xoff + nx <= ctx->wox + ctx->wsx) {
|
||||
/* All visible. */
|
||||
*i = 0;
|
||||
*x = ctx->xoff + px - ctx->wox;
|
||||
*rx = nx;
|
||||
} else if (xoff < ctx->wox && xoff + nx > ctx->wox + ctx->wsx) {
|
||||
} else if (xoff < (int)ctx->wox && xoff + nx > ctx->wox + ctx->wsx) {
|
||||
/* Both left and right not visible. */
|
||||
*i = ctx->wox;
|
||||
*x = 0;
|
||||
*rx = ctx->wsx;
|
||||
} else if (xoff < ctx->wox) {
|
||||
} else if (xoff < (int)ctx->wox) {
|
||||
/* Left not visible. */
|
||||
*i = ctx->wox - (ctx->xoff + px);
|
||||
*x = 0;
|
||||
@@ -1223,13 +1209,23 @@ static void
|
||||
tty_clear_pane_line(struct tty *tty, const struct tty_ctx *ctx, u_int py,
|
||||
u_int px, u_int nx, u_int bg)
|
||||
{
|
||||
struct client *c = tty->client;
|
||||
u_int i, x, rx, ry;
|
||||
struct client *c = tty->client;
|
||||
struct visible_ranges *r;
|
||||
struct visible_range *ri;
|
||||
u_int i, l, x, rx, ry;
|
||||
|
||||
log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py);
|
||||
|
||||
if (tty_clamp_line(tty, ctx, px, py, nx, &i, &x, &rx, &ry))
|
||||
tty_clear_line(tty, &ctx->defaults, ry, x, rx, bg);
|
||||
if (tty_clamp_line(tty, ctx, px, py, nx, &l, &x, &rx, &ry)) {
|
||||
r = tty_check_overlay_range(tty, x, ry, rx);
|
||||
for (i=0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx == 0)
|
||||
continue;
|
||||
tty_clear_line(tty, &ctx->defaults, ry, ri->px, ri->nx,
|
||||
bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clamp area position to visible part of pane. */
|
||||
@@ -1296,12 +1292,17 @@ tty_clamp_area(struct tty *tty, const struct tty_ctx *ctx, u_int px, u_int py,
|
||||
|
||||
/* Clear an area, adjusting to visible part of pane. */
|
||||
static void
|
||||
tty_clear_area(struct tty *tty, const struct grid_cell *defaults, u_int py,
|
||||
tty_clear_area(struct tty *tty, const struct tty_ctx *ctx, u_int py,
|
||||
u_int ny, u_int px, u_int nx, u_int bg)
|
||||
{
|
||||
struct client *c = tty->client;
|
||||
u_int yy;
|
||||
char tmp[64];
|
||||
struct client *c = tty->client;
|
||||
const struct grid_cell *defaults = &ctx->defaults;
|
||||
struct window *w = c->session->curw->window;
|
||||
struct window_pane *wpl, *wp = ctx->arg;
|
||||
struct visible_ranges *r;
|
||||
struct visible_range *ri;
|
||||
u_int i, yy, overlap = 0, oy = 0;
|
||||
char tmp[64];
|
||||
|
||||
log_debug("%s: %s, %u,%u at %u,%u", __func__, c->name, nx, ny, px, py);
|
||||
|
||||
@@ -1309,8 +1310,21 @@ tty_clear_area(struct tty *tty, const struct grid_cell *defaults, u_int py,
|
||||
if (nx == 0 || ny == 0)
|
||||
return;
|
||||
|
||||
/* Verify there's nothing overlapping in z-index before using BCE. */
|
||||
TAILQ_FOREACH(wpl, &w->z_index, zentry) {
|
||||
if (wpl == wp || ~wpl->flags & PANE_FLOATING)
|
||||
continue;
|
||||
if (wpl->xoff - 1 > (int)(px + nx) || wpl->xoff + wpl->sx + 1 < px)
|
||||
continue;
|
||||
if (wpl->yoff - 1 > (int)(py + ny) || wpl->yoff + wpl->sy + 1 < py)
|
||||
continue;
|
||||
overlap++;
|
||||
if (overlap > 0) break;
|
||||
}
|
||||
|
||||
/* If genuine BCE is available, can try escape sequences. */
|
||||
if (c->overlay_check == NULL && !tty_fake_bce(tty, defaults, bg)) {
|
||||
if (!overlap && c->overlay_check == NULL &&
|
||||
!tty_fake_bce(tty, defaults, bg)) {
|
||||
/* Use ED if clearing off the bottom of the terminal. */
|
||||
if (px == 0 &&
|
||||
px + nx >= tty->sx &&
|
||||
@@ -1361,9 +1375,18 @@ tty_clear_area(struct tty *tty, const struct grid_cell *defaults, u_int py,
|
||||
}
|
||||
}
|
||||
|
||||
if (c->session->statusat == 0)
|
||||
oy = c->session->statuslines;
|
||||
|
||||
/* Couldn't use an escape sequence, loop over the lines. */
|
||||
for (yy = py; yy < py + ny; yy++)
|
||||
tty_clear_line(tty, defaults, yy, px, nx, bg);
|
||||
for (yy = py; yy < py + ny; yy++) {
|
||||
r = tty_check_overlay_range(tty, px, yy - oy, nx);
|
||||
for (i=0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx == 0) continue;
|
||||
tty_clear_line(tty, defaults, yy, ri->px, ri->nx, bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear an area in a pane. */
|
||||
@@ -1371,28 +1394,57 @@ static void
|
||||
tty_clear_pane_area(struct tty *tty, const struct tty_ctx *ctx, u_int py,
|
||||
u_int ny, u_int px, u_int nx, u_int bg)
|
||||
{
|
||||
u_int i, j, x, y, rx, ry;
|
||||
u_int i, j, x, y, rx, ry;
|
||||
|
||||
if (tty_clamp_area(tty, ctx, px, py, nx, ny, &i, &j, &x, &y, &rx, &ry))
|
||||
tty_clear_area(tty, &ctx->defaults, y, ry, x, rx, bg);
|
||||
tty_clear_area(tty, ctx, y, ry, x, rx, bg);
|
||||
}
|
||||
|
||||
/* Redraw a line at py of a screen taking into account obscured ranges.
|
||||
* Menus and popups are always on top, ctx->arg == NULL.
|
||||
*/
|
||||
static void
|
||||
tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py)
|
||||
{
|
||||
struct screen *s = ctx->s;
|
||||
u_int nx = ctx->sx, i, x, rx, ry;
|
||||
struct screen *s = ctx->s;
|
||||
struct window_pane *wp = ctx->arg;
|
||||
struct visible_ranges *r = NULL;
|
||||
struct visible_range *ri;
|
||||
u_int nx = ctx->sx, i, px, x, rx, ry;
|
||||
|
||||
log_debug("%s: %s %u %d", __func__, tty->client->name, py, ctx->bigger);
|
||||
|
||||
if (!ctx->bigger) {
|
||||
tty_draw_line(tty, s, 0, py, nx, ctx->xoff, ctx->yoff + py,
|
||||
&ctx->defaults, ctx->palette);
|
||||
if (wp) {
|
||||
r = tty_check_overlay_range(tty, 0, ctx->yoff + py, nx);
|
||||
for (i=0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx == 0) continue;
|
||||
tty_draw_line(tty, s, ri->px, py, ri->nx,
|
||||
ctx->xoff + ri->px, ctx->yoff + py,
|
||||
&ctx->defaults, ctx->palette);
|
||||
}
|
||||
} else {
|
||||
tty_draw_line(tty, s, 0, py, nx, ctx->xoff,
|
||||
ctx->yoff + py, &ctx->defaults, ctx->palette);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (tty_clamp_line(tty, ctx, 0, py, nx, &i, &x, &rx, &ry)) {
|
||||
tty_draw_line(tty, s, i, py, rx, x, ry, &ctx->defaults,
|
||||
ctx->palette);
|
||||
if (tty_clamp_line(tty, ctx, 0, py, nx, &px, &x, &rx, &ry)) {
|
||||
if (wp) {
|
||||
r = tty_check_overlay_range(tty, i, py, rx);
|
||||
for (i=0; i < r->used; i++) {
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx == 0)
|
||||
continue;
|
||||
tty_draw_line(tty, s, i, py, ri->nx,
|
||||
x + ri->px, ry, &ctx->defaults,
|
||||
ctx->palette);
|
||||
}
|
||||
} else {
|
||||
tty_draw_line(tty, s, px, py, rx, x, ry, &ctx->defaults,
|
||||
ctx->palette);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1459,9 +1511,9 @@ tty_check_overlay_range(struct tty *tty, u_int px, u_int py, u_int nx)
|
||||
return (c->overlay_check(c, c->overlay_data, px, py, nx));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
/* Update context for client. */
|
||||
int
|
||||
static int
|
||||
tty_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
|
||||
{
|
||||
struct window_pane *wp = ttyctx->arg;
|
||||
@@ -1475,7 +1527,7 @@ tty_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
|
||||
ttyctx->bigger = tty_window_offset(&c->tty, &ttyctx->wox, &ttyctx->woy,
|
||||
&ttyctx->wsx, &ttyctx->wsy);
|
||||
|
||||
ttyctx->yoff = ttyctx->ryoff = wp->yoff;
|
||||
ttyctx->yoff = ttyctx->ryoff = wp->yoff; /* xxxx find another way to do this */
|
||||
if (status_at_line(c) == 0)
|
||||
ttyctx->yoff += status_line_size(c);
|
||||
|
||||
@@ -1503,25 +1555,10 @@ tty_draw_images(struct client *c, struct window_pane *wp, struct screen *s)
|
||||
ttyctx.sy = wp->sy;
|
||||
|
||||
ttyctx.ptr = im;
|
||||
ttyctx.arg = wp;
|
||||
ttyctx.arg = wp; /* xxx remove this */
|
||||
ttyctx.set_client_cb = tty_set_client_cb;
|
||||
ttyctx.allow_invisible_panes = 1;
|
||||
|
||||
/* Call the appropriate rendering function based on image type */
|
||||
switch (im->type) {
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
case IMAGE_SIXEL:
|
||||
tty_write_one(tty_cmd_sixelimage, c, &ttyctx);
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
case IMAGE_KITTY:
|
||||
tty_write_one(tty_cmd_kittyimage, c, &ttyctx);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
tty_write_one(tty_cmd_sixelimage, c, &ttyctx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1599,7 +1636,7 @@ tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *),
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
/* Only write to the incoming tty instead of every client. */
|
||||
static void
|
||||
tty_write_one(void (*cmdfn)(struct tty *, const struct tty_ctx *),
|
||||
@@ -1832,8 +1869,8 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
|
||||
void
|
||||
tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
struct client *c = tty->client;
|
||||
u_int i;
|
||||
struct client *c = tty->client;
|
||||
u_int i;
|
||||
|
||||
if (ctx->bigger ||
|
||||
(!tty_full_width(tty, ctx) && !tty_use_margin(tty)) ||
|
||||
@@ -1841,7 +1878,8 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
|
||||
!tty_term_has(tty->term, TTYC_CSR) ||
|
||||
ctx->sx == 1 ||
|
||||
ctx->sy == 1 ||
|
||||
c->overlay_check != NULL) {
|
||||
c->overlay_check != NULL ||
|
||||
ctx->obscured) {
|
||||
tty_redraw_region(tty, ctx);
|
||||
return;
|
||||
}
|
||||
@@ -1999,7 +2037,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
const struct grid_cell *gcp = ctx->cell;
|
||||
struct screen *s = ctx->s;
|
||||
struct visible_ranges *r;
|
||||
struct visible_ranges *r = NULL;
|
||||
u_int px, py, i, vis = 0;
|
||||
|
||||
px = ctx->xoff + ctx->ocx - ctx->wox;
|
||||
@@ -2009,6 +2047,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
||||
return;
|
||||
|
||||
if (ctx->num == 2) {
|
||||
/* xxxx need to check visible range */
|
||||
tty_draw_line(tty, s, 0, s->cy, screen_size_x(s),
|
||||
ctx->xoff - ctx->wox, py, &ctx->defaults, ctx->palette);
|
||||
return;
|
||||
@@ -2034,8 +2073,9 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
|
||||
tty_margin_off(tty);
|
||||
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
|
||||
|
||||
tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette,
|
||||
ctx->s->hyperlinks);
|
||||
if (screen_redraw_is_visible(r, px))
|
||||
tty_cell(tty, ctx->cell, &ctx->defaults, ctx->palette,
|
||||
ctx->s->hyperlinks);
|
||||
|
||||
if (ctx->num == 1)
|
||||
tty_invalidate(tty);
|
||||
@@ -2045,7 +2085,7 @@ void
|
||||
tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
struct visible_ranges *r;
|
||||
struct visible_range *rr;
|
||||
struct visible_range *ri;
|
||||
u_int i, px, py, cx;
|
||||
char *cp = ctx->ptr;
|
||||
|
||||
@@ -2079,11 +2119,11 @@ tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
|
||||
|
||||
r = tty_check_overlay_range(tty, px, py, ctx->num);
|
||||
for (i = 0; i < r->used; i++) {
|
||||
rr = &r->ranges[i];
|
||||
if (rr->nx != 0) {
|
||||
cx = rr->px - ctx->xoff + ctx->wox;
|
||||
ri = &r->ranges[i];
|
||||
if (ri->nx != 0) {
|
||||
cx = ri->px - ctx->xoff + ctx->wox;
|
||||
tty_cursor_pane_unless_wrap(tty, ctx, cx, ctx->ocy);
|
||||
tty_putn(tty, cp + rr->px - px, rr->nx, rr->nx);
|
||||
tty_putn(tty, cp + ri->px - px, ri->nx, ri->nx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2124,12 +2164,12 @@ tty_cmd_rawstring(struct tty *tty, const struct tty_ctx *ctx)
|
||||
tty_invalidate(tty);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SIXEL_IMAGES
|
||||
#ifdef ENABLE_SIXEL
|
||||
void
|
||||
tty_cmd_sixelimage(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
struct image *im = ctx->ptr;
|
||||
struct sixel_image *si = im->data.sixel;
|
||||
struct sixel_image *si = im->data;
|
||||
struct sixel_image *new;
|
||||
char *data;
|
||||
size_t size;
|
||||
@@ -2176,142 +2216,6 @@ tty_cmd_sixelimage(struct tty *tty, const struct tty_ctx *ctx)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_KITTY_IMAGES
|
||||
static int
|
||||
tty_has_kitty(struct tty *tty)
|
||||
{
|
||||
return (tty->term->flags & TERM_KITTY);
|
||||
}
|
||||
|
||||
void
|
||||
tty_cmd_kittyimage(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
struct image *im = ctx->ptr;
|
||||
char *data;
|
||||
size_t size;
|
||||
u_int cx = ctx->ocx, cy = ctx->ocy;
|
||||
int fallback = 0;
|
||||
|
||||
if (im == NULL || im->data.kitty == NULL)
|
||||
return;
|
||||
|
||||
/* Check if this terminal supports kitty graphics. */
|
||||
if (!tty_has_kitty(tty))
|
||||
fallback = 1;
|
||||
|
||||
log_debug("%s: image at %u,%u (fallback=%d)", __func__, cx, cy,
|
||||
fallback);
|
||||
|
||||
if (fallback == 1) {
|
||||
/* Use text fallback for non-kitty terminals. */
|
||||
data = xstrdup(im->fallback);
|
||||
size = strlen(data);
|
||||
} else {
|
||||
/* Re-serialize the kitty image command. */
|
||||
data = kitty_print(im->data.kitty, &size);
|
||||
}
|
||||
|
||||
if (data != NULL) {
|
||||
log_debug("%s: %zu bytes", __func__, size);
|
||||
tty_region_off(tty);
|
||||
tty_margin_off(tty);
|
||||
tty_cursor(tty, cx + ctx->xoff, cy + ctx->yoff);
|
||||
|
||||
tty->flags |= TTY_NOBLOCK;
|
||||
tty_add(tty, data, size);
|
||||
tty_invalidate(tty);
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass a kitty APC sequence directly to all attached kitty-capable clients
|
||||
* showing the given pane. The outer terminal's cursor is first moved to
|
||||
* the pane-relative position (cx, cy) so that images placed at "current
|
||||
* cursor" land in the right spot. Pass cx=cy=UINT_MAX to skip cursor
|
||||
* positioning (e.g. for delete commands that don't depend on position).
|
||||
*/
|
||||
void
|
||||
tty_kitty_passthrough(struct window_pane *wp, const char *data, size_t len,
|
||||
u_int cx, u_int cy)
|
||||
{
|
||||
struct client *c;
|
||||
struct tty *tty;
|
||||
u_int x, y;
|
||||
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session == NULL || c->tty.term == NULL)
|
||||
continue;
|
||||
if (c->flags & CLIENT_SUSPENDED)
|
||||
continue;
|
||||
if (c->tty.flags & TTY_FREEZE)
|
||||
continue;
|
||||
tty = &c->tty;
|
||||
if (!tty_has_kitty(tty))
|
||||
continue;
|
||||
if (c->session->curw->window != wp->window)
|
||||
continue;
|
||||
if (!window_pane_visible(wp))
|
||||
continue;
|
||||
|
||||
/* Position cursor at the correct screen location. */
|
||||
if (cx != UINT_MAX && cy != UINT_MAX) {
|
||||
x = wp->xoff + cx;
|
||||
y = wp->yoff + cy;
|
||||
if (status_at_line(c) == 0)
|
||||
y += status_line_size(c);
|
||||
tty_region_off(tty);
|
||||
tty_margin_off(tty);
|
||||
tty_cursor(tty, x, y);
|
||||
}
|
||||
|
||||
tty->flags |= TTY_NOBLOCK;
|
||||
tty_add(tty, data, len);
|
||||
tty_invalidate(tty);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all kitty image placements from the outer terminal unconditionally.
|
||||
* Called directly (not via tty_write) so it fires on every full window
|
||||
* redraw regardless of whether the current window has any stored images.
|
||||
*/
|
||||
void
|
||||
tty_kitty_delete_all(struct tty *tty)
|
||||
{
|
||||
char *data;
|
||||
size_t size;
|
||||
|
||||
if (!tty_has_kitty(tty))
|
||||
return;
|
||||
|
||||
if ((data = kitty_delete_all(&size)) == NULL)
|
||||
return;
|
||||
|
||||
tty->flags |= TTY_NOBLOCK;
|
||||
tty_add(tty, data, size);
|
||||
tty_invalidate(tty);
|
||||
free(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all kitty image placements via passthrough for a specific pane.
|
||||
* Used on terminal reset (RIS) so images are cleared from the outer terminal.
|
||||
*/
|
||||
void
|
||||
tty_kitty_delete_all_pane(struct window_pane *wp)
|
||||
{
|
||||
char *data;
|
||||
size_t size;
|
||||
|
||||
if ((data = kitty_delete_all(&size)) == NULL)
|
||||
return;
|
||||
|
||||
tty_kitty_passthrough(wp, data, size, UINT_MAX, UINT_MAX);
|
||||
free(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
tty_cmd_syncstart(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
@@ -2461,8 +2365,17 @@ tty_margin_off(struct tty *tty)
|
||||
static void
|
||||
tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx)
|
||||
{
|
||||
tty_margin(tty, ctx->xoff - ctx->wox,
|
||||
ctx->xoff + ctx->sx - 1 - ctx->wox);
|
||||
int l, r;
|
||||
|
||||
l = ctx->xoff - ctx->wox;
|
||||
r = ctx->xoff + ctx->sx - 1 - ctx->wox;
|
||||
|
||||
if (l < 0) l = 0;
|
||||
if (l > (int)ctx->wsx) l = ctx->wsx;
|
||||
if (r < 0) r = 0;
|
||||
if (r > (int)ctx->wsx) r = ctx->wsx;
|
||||
|
||||
tty_margin(tty, l, r);
|
||||
}
|
||||
|
||||
/* Set margin at absolute position. */
|
||||
|
||||
@@ -42,7 +42,7 @@ static void window_copy_formats(struct window_mode_entry *,
|
||||
struct format_tree *);
|
||||
static struct screen *window_copy_get_screen(struct window_mode_entry *);
|
||||
static void window_copy_scroll1(struct window_mode_entry *,
|
||||
struct window_pane *wp, int, u_int, int);
|
||||
struct window_pane *wp, int, u_int, u_int, int);
|
||||
static void window_copy_pageup1(struct window_mode_entry *, int);
|
||||
static int window_copy_pagedown1(struct window_mode_entry *, int, int);
|
||||
static void window_copy_next_paragraph(struct window_mode_entry *);
|
||||
@@ -596,19 +596,19 @@ window_copy_vadd(struct window_pane *wp, int parse, const char *fmt, va_list ap)
|
||||
|
||||
void
|
||||
window_copy_scroll(struct window_pane *wp, int sl_mpos, u_int my,
|
||||
int scroll_exit)
|
||||
u_int tty_oy, int scroll_exit)
|
||||
{
|
||||
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
|
||||
|
||||
if (wme != NULL) {
|
||||
window_set_active_pane(wp->window, wp, 0);
|
||||
window_copy_scroll1(wme, wp, sl_mpos, my, scroll_exit);
|
||||
window_copy_scroll1(wme, wp, sl_mpos, my, tty_oy, scroll_exit);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp,
|
||||
int sl_mpos, u_int my, int scroll_exit)
|
||||
int sl_mpos, u_int my, u_int tty_oy, int scroll_exit)
|
||||
{
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
u_int ox, oy, px, py, n, offset, size;
|
||||
@@ -616,21 +616,29 @@ window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp,
|
||||
u_int slider_height = wp->sb_slider_h;
|
||||
u_int sb_height = wp->sy, sb_top = wp->yoff;
|
||||
u_int sy = screen_size_y(data->backing);
|
||||
u_int my_w;
|
||||
int new_slider_y, delta;
|
||||
|
||||
/*
|
||||
* sl_mpos is where in the slider the user is dragging, mouse is
|
||||
* dragging this y point relative to top of slider.
|
||||
*
|
||||
* my is a raw tty y coordinate; sb_top (= wp->yoff) is a window
|
||||
* coordinate. Convert my to window coordinates by adding tty_oy
|
||||
* (the window pan offset). sl_mpos already has the statuslines
|
||||
* adjustment baked in (see server_client_check_mouse), so no further
|
||||
* statuslines correction is needed here.
|
||||
*/
|
||||
if (my <= sb_top + sl_mpos) {
|
||||
my_w = my + tty_oy;
|
||||
if (my_w <= sb_top + (u_int)sl_mpos) {
|
||||
/* Slider banged into top. */
|
||||
new_slider_y = sb_top - wp->yoff;
|
||||
} else if (my - sl_mpos > sb_top + sb_height - slider_height) {
|
||||
} else if (my_w - sl_mpos > sb_top + sb_height - slider_height) {
|
||||
/* Slider banged into bottom. */
|
||||
new_slider_y = sb_top - wp->yoff + (sb_height - slider_height);
|
||||
} else {
|
||||
/* Slider is somewhere in the middle. */
|
||||
new_slider_y = my - wp->yoff - sl_mpos;
|
||||
new_slider_y = my_w - wp->yoff - sl_mpos;
|
||||
}
|
||||
|
||||
if (TAILQ_FIRST(&wp->modes) == NULL ||
|
||||
@@ -1503,8 +1511,11 @@ window_copy_cmd_scroll_to_mouse(struct window_copy_cmd_state *cs)
|
||||
struct client *c = cs->c;
|
||||
struct mouse_event *m = cs->m;
|
||||
int scroll_exit = args_has(cs->wargs, 'e');
|
||||
u_int tty_ox, tty_oy, tty_sx, tty_sy;
|
||||
|
||||
window_copy_scroll(wp, c->tty.mouse_slider_mpos, m->y, scroll_exit);
|
||||
tty_window_offset(&c->tty, &tty_ox, &tty_oy, &tty_sx, &tty_sy);
|
||||
window_copy_scroll(wp, c->tty.mouse_slider_mpos, m->y, tty_oy,
|
||||
scroll_exit);
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
|
||||
@@ -4705,7 +4716,7 @@ window_copy_write_lines(struct window_mode_entry *wme,
|
||||
u_int yy;
|
||||
|
||||
for (yy = py; yy < py + ny; yy++)
|
||||
window_copy_write_line(wme, ctx, py);
|
||||
window_copy_write_line(wme, ctx, yy);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -6071,7 +6082,10 @@ window_copy_drag_update(struct client *c, struct mouse_event *m)
|
||||
if (c == NULL)
|
||||
return;
|
||||
|
||||
wp = cmd_mouse_pane(m, NULL, NULL);
|
||||
if (c->tty.mouse_wp != NULL)
|
||||
wp = c->tty.mouse_wp;
|
||||
else
|
||||
wp = cmd_mouse_pane(m, NULL, NULL);
|
||||
if (wp == NULL)
|
||||
return;
|
||||
wme = TAILQ_FIRST(&wp->modes);
|
||||
|
||||
136
window.c
136
window.c
@@ -306,6 +306,7 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel)
|
||||
w->flags = 0;
|
||||
|
||||
TAILQ_INIT(&w->panes);
|
||||
TAILQ_INIT(&w->z_index);
|
||||
TAILQ_INIT(&w->last_panes);
|
||||
w->active = NULL;
|
||||
|
||||
@@ -527,6 +528,8 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
||||
|
||||
if (wp == w->active)
|
||||
return (0);
|
||||
if (w->flags & WINDOW_ZOOMED)
|
||||
window_unzoom(w, 1);
|
||||
lastwp = w->active;
|
||||
|
||||
window_pane_stack_remove(&w->last_panes, wp);
|
||||
@@ -536,6 +539,20 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
||||
w->active->active_point = next_active_point++;
|
||||
w->active->flags |= PANE_CHANGED;
|
||||
|
||||
if (wp->flags & PANE_MINIMISED) {
|
||||
wp->flags &= ~PANE_MINIMISED;
|
||||
if (w->layout_root != NULL) {
|
||||
wp->layout_cell = wp->saved_layout_cell;
|
||||
wp->saved_layout_cell = NULL;
|
||||
layout_unminimise_cell(w, wp->layout_cell);
|
||||
layout_fix_offsets(w);
|
||||
layout_fix_panes(w, NULL);
|
||||
}
|
||||
}
|
||||
notify_window("window-layout-changed", w);
|
||||
server_redraw_window(w);
|
||||
|
||||
|
||||
if (options_get_number(global_options, "focus-events")) {
|
||||
window_pane_update_focus(lastwp);
|
||||
window_pane_update_focus(w->active);
|
||||
@@ -548,6 +565,33 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
window_deactivate_pane(struct window *w, struct window_pane *wp, int notify)
|
||||
{
|
||||
struct window_pane *lastwp;
|
||||
|
||||
log_debug("%s: pane %%%u", __func__, wp->id);
|
||||
|
||||
if (w->flags & WINDOW_ZOOMED)
|
||||
window_unzoom(w, 1);
|
||||
lastwp = w->active;
|
||||
|
||||
window_pane_stack_remove(&w->last_panes, wp);
|
||||
window_pane_stack_push(&w->last_panes, lastwp);
|
||||
|
||||
w->active = NULL;
|
||||
|
||||
if (options_get_number(global_options, "focus-events")) {
|
||||
window_pane_update_focus(lastwp);
|
||||
}
|
||||
|
||||
tty_update_window_offset(w);
|
||||
|
||||
if (notify)
|
||||
notify_window("window-pane-changed", w);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
window_pane_get_palette(struct window_pane *wp, int c)
|
||||
{
|
||||
@@ -588,7 +632,20 @@ window_redraw_active_switch(struct window *w, struct window_pane *wp)
|
||||
}
|
||||
if (wp == w->active)
|
||||
break;
|
||||
|
||||
/* If you want tiled planes to be able to bury
|
||||
* floating planes then do this regardless of
|
||||
* wp->flags & PANE_FLOATING or not. A new option?
|
||||
*/
|
||||
if (wp->flags & PANE_FLOATING) {
|
||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
|
||||
wp->flags |= PANE_REDRAW;
|
||||
}
|
||||
|
||||
wp = w->active;
|
||||
if (wp == NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,16 +653,34 @@ struct window_pane *
|
||||
window_get_active_at(struct window *w, u_int x, u_int y)
|
||||
{
|
||||
struct window_pane *wp;
|
||||
u_int xoff, yoff, sx, sy;
|
||||
int status, xoff, yoff;
|
||||
u_int sx, sy;
|
||||
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
status = options_get_number(w->options, "pane-border-status");
|
||||
|
||||
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||
if (!window_pane_visible(wp))
|
||||
continue;
|
||||
window_pane_full_size_offset(wp, &xoff, &yoff, &sx, &sy);
|
||||
if (x < xoff || x > xoff + sx)
|
||||
continue;
|
||||
if (y < yoff || y > yoff + sy)
|
||||
continue;
|
||||
if (~wp->flags & PANE_FLOATING) {
|
||||
/* Tiled, select up to including bottom or
|
||||
right border. */
|
||||
if ((int)x < xoff || x > xoff + sx)
|
||||
continue;
|
||||
if (status == PANE_STATUS_TOP) {
|
||||
if ((int)y < yoff - 1 || y > yoff + sy)
|
||||
continue;
|
||||
} else {
|
||||
if ((int)y < yoff || y > yoff + sy)
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/* Floating, include top or or left border. */
|
||||
if ((int)x < xoff - 1 || x > xoff + sx)
|
||||
continue;
|
||||
if ((int)y < yoff - 1 || y > yoff + sy)
|
||||
continue;
|
||||
}
|
||||
return (wp);
|
||||
}
|
||||
return (NULL);
|
||||
@@ -661,12 +736,24 @@ window_zoom(struct window_pane *wp)
|
||||
if (w->flags & WINDOW_ZOOMED)
|
||||
return (-1);
|
||||
|
||||
if (window_count_panes(w) == 1)
|
||||
return (-1);
|
||||
|
||||
if (w->active != wp)
|
||||
window_set_active_pane(w, wp, 1);
|
||||
|
||||
/* Bring pane above other tiled panes and minimise floating panes. */
|
||||
TAILQ_FOREACH(wp1, &w->z_index, zentry) {
|
||||
if (wp1 == wp) {
|
||||
wp1->saved_flags |= (wp1->flags & PANE_MINIMISED);
|
||||
wp1->flags &= ~PANE_MINIMISED;
|
||||
continue;
|
||||
}
|
||||
if (wp1->flags & PANE_FLOATING) {
|
||||
wp1->saved_flags |= (wp1->flags & PANE_MINIMISED);
|
||||
wp1->flags |= PANE_MINIMISED;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(wp1, &w->panes, entry) {
|
||||
wp1->saved_layout_cell = wp1->layout_cell;
|
||||
wp1->layout_cell = NULL;
|
||||
@@ -693,6 +780,14 @@ window_unzoom(struct window *w, int notify)
|
||||
w->layout_root = w->saved_layout_root;
|
||||
w->saved_layout_root = NULL;
|
||||
|
||||
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||
if (wp->flags & PANE_FLOATING) {
|
||||
wp->flags &= ~PANE_MINIMISED | (wp->saved_flags & PANE_MINIMISED);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
wp->layout_cell = wp->saved_layout_cell;
|
||||
wp->saved_layout_cell = NULL;
|
||||
@@ -748,11 +843,17 @@ window_add_pane(struct window *w, struct window_pane *other, u_int hlimit,
|
||||
TAILQ_INSERT_BEFORE(other, wp, entry);
|
||||
} else {
|
||||
log_debug("%s: @%u after %%%u", __func__, w->id, wp->id);
|
||||
if (flags & SPAWN_FULLSIZE)
|
||||
if (flags & (SPAWN_FULLSIZE|SPAWN_FLOATING))
|
||||
TAILQ_INSERT_TAIL(&w->panes, wp, entry);
|
||||
else
|
||||
TAILQ_INSERT_AFTER(&w->panes, other, wp, entry);
|
||||
}
|
||||
/* Floating panes are created above tiled planes. */
|
||||
if (flags & SPAWN_FLOATING) {
|
||||
wp->flags |= PANE_FLOATING;
|
||||
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
|
||||
} else
|
||||
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
|
||||
return (wp);
|
||||
}
|
||||
|
||||
@@ -787,6 +888,7 @@ window_remove_pane(struct window *w, struct window_pane *wp)
|
||||
window_lost_pane(w, wp);
|
||||
|
||||
TAILQ_REMOVE(&w->panes, wp, entry);
|
||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||
window_pane_destroy(wp);
|
||||
}
|
||||
|
||||
@@ -870,6 +972,7 @@ window_destroy_panes(struct window *w)
|
||||
while (!TAILQ_EMPTY(&w->panes)) {
|
||||
wp = TAILQ_FIRST(&w->panes);
|
||||
TAILQ_REMOVE(&w->panes, wp, entry);
|
||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||
window_pane_destroy(wp);
|
||||
}
|
||||
}
|
||||
@@ -1105,6 +1208,15 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
wme->mode->resize(wme, sx, sy);
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_move(struct window_pane *wp, int xoff, int yoff)
|
||||
{
|
||||
wp->xoff = xoff;
|
||||
wp->yoff = yoff;
|
||||
|
||||
log_debug("%s: %%%u resize %ux%u", __func__, wp->id, xoff, yoff);
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_set_mode(struct window_pane *wp, struct window_pane *swp,
|
||||
const struct window_mode *mode, struct cmd_find_state *fs,
|
||||
@@ -1272,8 +1384,10 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
|
||||
int
|
||||
window_pane_visible(struct window_pane *wp)
|
||||
{
|
||||
if (~wp->window->flags & WINDOW_ZOOMED)
|
||||
if (~wp->window->flags & WINDOW_ZOOMED &&
|
||||
~wp->flags & PANE_MINIMISED)
|
||||
return (1);
|
||||
|
||||
return (wp == wp->window->active);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user