mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-02 01:40:13 -05:00
multi-cursor: wip: track cursor shapes and colors
And erase all extra cursors on reset, resize and clear screen/scrollback (ED 2/3).
This commit is contained in:
parent
dccbdb97cd
commit
beb4556dc0
4 changed files with 92 additions and 31 deletions
76
csi.c
76
csi.c
|
|
@ -987,11 +987,15 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
/* Erase entire screen */
|
/* Erase entire screen */
|
||||||
term_erase(term, 0, 0, term->rows - 1, term->cols - 1);
|
term_erase(term, 0, 0, term->rows - 1, term->cols - 1);
|
||||||
term->grid->cursor.lcf = false;
|
term->grid->cursor.lcf = false;
|
||||||
|
if (unlikely(term->multi_cursor.shapes != NULL))
|
||||||
|
term_remove_all_multi_cursors(term);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: {
|
case 3: {
|
||||||
/* Erase scrollback */
|
/* Erase scrollback */
|
||||||
term_erase_scrollback(term);
|
term_erase_scrollback(term);
|
||||||
|
if (unlikely(term->multi_cursor.shapes != NULL))
|
||||||
|
term_remove_all_multi_cursors(term);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2229,7 +2233,7 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
switch (final) {
|
switch (final) {
|
||||||
case 'q': {
|
case 'q': {
|
||||||
if (term->vt.params.idx == 0) {
|
if (term->vt.params.idx == 0) {
|
||||||
LOG_WARN("multi-cursor: query support");
|
LOG_WARN("multi-cursor: unimplemented: query support");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2300,18 +2304,6 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_WARN("modified cursor locations:");
|
|
||||||
int rect_count = 0;
|
|
||||||
const pixman_box32_t *boxes = pixman_region32_rectangles(&modified, &rect_count);
|
|
||||||
for (int j = 0; j < rect_count; j++) {
|
|
||||||
const pixman_box32_t *box = &boxes[j];
|
|
||||||
for (int r = box->y1; r < box->y2; r++) {
|
|
||||||
for (int c = box->x1; c < box->x2; c++) {
|
|
||||||
LOG_WARN(" (%d, %d)", r, c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shape == 0) {
|
if (shape == 0) {
|
||||||
/* Cursors disabled, remove from active set */
|
/* Cursors disabled, remove from active set */
|
||||||
pixman_region32_subtract(&term->multi_cursor.active, &term->multi_cursor.active, &modified);
|
pixman_region32_subtract(&term->multi_cursor.active, &term->multi_cursor.active, &modified);
|
||||||
|
|
@ -2320,34 +2312,45 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
pixman_region32_union(&term->multi_cursor.active, &term->multi_cursor.active, &modified);
|
pixman_region32_union(&term->multi_cursor.active, &term->multi_cursor.active, &modified);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_WARN("active multi-cursor locations:");
|
if (pixman_region32_empty(&term->multi_cursor.active)) {
|
||||||
rect_count = 0;
|
free(term->multi_cursor.shapes);
|
||||||
boxes = pixman_region32_rectangles(&term->multi_cursor.active, &rect_count);
|
term->multi_cursor.shapes = NULL;
|
||||||
for (int j = 0; j < rect_count; j++) {
|
} else {
|
||||||
const pixman_box32_t *box = &boxes[j];
|
if (term->multi_cursor.shapes == NULL) {
|
||||||
for (int r = box->y1; r < box->y2; r++) {
|
term->multi_cursor.shapes = xcalloc(
|
||||||
for (int c = box->x1; c < box->x2; c++) {
|
term->cols * term->rows,
|
||||||
LOG_WARN(" (%d, %d)", r, c);
|
sizeof(enum multi_cursor_shape));
|
||||||
|
}
|
||||||
|
|
||||||
|
int rect_count = 0;
|
||||||
|
const pixman_box32_t *boxes = pixman_region32_rectangles(&modified, &rect_count);
|
||||||
|
for (int j = 0; j < rect_count; j++) {
|
||||||
|
const pixman_box32_t *box = &boxes[j];
|
||||||
|
for (int r = box->y1; r < box->y2; r++) {
|
||||||
|
for (int c = box->x1; c < box->x2; c++) {
|
||||||
|
term->multi_cursor.shapes[r * term->cols + c] = shape;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_WARN("multi-cursors are now %s", pixman_region32_not_empty(&term->multi_cursor.active) ? "active" : "disabled");
|
|
||||||
pixman_region32_fini(&modified);
|
pixman_region32_fini(&modified);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 30:
|
case 30:
|
||||||
case 40:
|
case 40: {
|
||||||
LOG_WARN("multi-cursor: change color of %s", shape == 30 ? "text under cursor" : "cursor");
|
|
||||||
|
|
||||||
const unsigned color_space = vt_param_get(term, 1, 0);
|
const unsigned color_space = vt_param_get(term, 1, 0);
|
||||||
|
enum multi_cursor_color_source color_source = MULTI_CURSOR_COLOR_PRIMARY;
|
||||||
|
uint32_t color = shape == 30 ? term->multi_cursor.text_color
|
||||||
|
: term->multi_cursor.cursor_color;
|
||||||
|
|
||||||
switch (color_space) {
|
switch (color_space) {
|
||||||
case 0:
|
case 0:
|
||||||
LOG_WARN("use main cursor colors");
|
color_source = MULTI_CURSOR_COLOR_PRIMARY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
LOG_WARN("special (reverse)");
|
color_source = MULTI_CURSOR_COLOR_SPECIAL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: {
|
case 2: {
|
||||||
|
|
@ -2356,7 +2359,8 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
const uint8_t red = param->sub.value[0];
|
const uint8_t red = param->sub.value[0];
|
||||||
const uint8_t green = param->sub.value[1];
|
const uint8_t green = param->sub.value[1];
|
||||||
const uint8_t blue = param->sub.value[2];
|
const uint8_t blue = param->sub.value[2];
|
||||||
LOG_WARN("red=%hhu, green=%hhu, blue=%hhu", red, green, blue);
|
color_source = MULTI_CURSOR_COLOR_RGB;
|
||||||
|
color = 0xffu << 24 | red << 16 | green << 8 | blue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -2365,7 +2369,8 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
const struct vt_param *param = &term->vt.params.v[1];
|
const struct vt_param *param = &term->vt.params.v[1];
|
||||||
if (param->sub.idx == 1) {
|
if (param->sub.idx == 1) {
|
||||||
const unsigned color_index = param->sub.value[0];
|
const unsigned color_index = param->sub.value[0];
|
||||||
LOG_WARN("indexed color=%u", color_index);
|
color_source = MULTI_CURSOR_COLOR_RGB;
|
||||||
|
color = color_index;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -2374,14 +2379,23 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
||||||
LOG_WARN("multi-cursor: invalid color space: %u", color_space);
|
LOG_WARN("multi-cursor: invalid color space: %u", color_space);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shape == 30) {
|
||||||
|
term->multi_cursor.text_color_source = color_source;
|
||||||
|
term->multi_cursor.text_color = color;
|
||||||
|
} else {
|
||||||
|
term->multi_cursor.cursor_color_source = color_source;
|
||||||
|
term->multi_cursor.cursor_color = color;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 100:
|
case 100:
|
||||||
LOG_WARN("multi-cursor: query extra cursors");
|
LOG_WARN("multi-cursor: unimplemented: query extra cursors");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 101:
|
case 101:
|
||||||
LOG_WARN("multi-cursor: query extra cursors' color");
|
LOG_WARN("multi-cursor: unimplemented: query extra cursors' color");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
2
render.c
2
render.c
|
|
@ -4812,6 +4812,8 @@ render_resize(struct terminal *term, int width, int height, uint8_t opts)
|
||||||
|
|
||||||
term->render.last_cursor.row = NULL;
|
term->render.last_cursor.row = NULL;
|
||||||
|
|
||||||
|
term_remove_all_multi_cursors(term);
|
||||||
|
|
||||||
damage_view:
|
damage_view:
|
||||||
/* Signal TIOCSWINSZ */
|
/* Signal TIOCSWINSZ */
|
||||||
send_dimensions_to_client(term);
|
send_dimensions_to_client(term);
|
||||||
|
|
|
||||||
21
terminal.c
21
terminal.c
|
|
@ -1404,6 +1404,11 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
||||||
.ime_enabled = true,
|
.ime_enabled = true,
|
||||||
#endif
|
#endif
|
||||||
.active_notifications = tll_init(),
|
.active_notifications = tll_init(),
|
||||||
|
.multi_cursor = {
|
||||||
|
.shapes = NULL,
|
||||||
|
.cursor_color = MULTI_CURSOR_COLOR_PRIMARY,
|
||||||
|
.text_color = MULTI_CURSOR_COLOR_PRIMARY,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pixman_region32_init(&term->render.last_overlay_clip);
|
pixman_region32_init(&term->render.last_overlay_clip);
|
||||||
|
|
@ -1946,6 +1951,7 @@ term_destroy(struct terminal *term)
|
||||||
free(term->color_stack.stack);
|
free(term->color_stack.stack);
|
||||||
|
|
||||||
pixman_region32_fini(&term->multi_cursor.active);
|
pixman_region32_fini(&term->multi_cursor.active);
|
||||||
|
free(term->multi_cursor.shapes);
|
||||||
|
|
||||||
int ret = EXIT_SUCCESS;
|
int ret = EXIT_SUCCESS;
|
||||||
|
|
||||||
|
|
@ -2090,6 +2096,15 @@ term_theme_apply(struct terminal *term, const struct color_theme *theme)
|
||||||
memcpy(term->colors.table, theme->table, sizeof(term->colors.table));
|
memcpy(term->colors.table, theme->table, sizeof(term->colors.table));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
term_remove_all_multi_cursors(struct terminal *term)
|
||||||
|
{
|
||||||
|
pixman_region32_fini(&term->multi_cursor.active);
|
||||||
|
pixman_region32_init(&term->multi_cursor.active);
|
||||||
|
free(term->multi_cursor.shapes);
|
||||||
|
term->multi_cursor.shapes = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
term_reset(struct terminal *term, bool hard)
|
term_reset(struct terminal *term, bool hard)
|
||||||
{
|
{
|
||||||
|
|
@ -2170,6 +2185,12 @@ term_reset(struct terminal *term, bool hard)
|
||||||
term->bits_affecting_ascii_printer.value = 0;
|
term->bits_affecting_ascii_printer.value = 0;
|
||||||
term_update_ascii_printer(term);
|
term_update_ascii_printer(term);
|
||||||
|
|
||||||
|
term_remove_all_multi_cursors(term);
|
||||||
|
term->multi_cursor.cursor_color_source = MULTI_CURSOR_COLOR_PRIMARY;
|
||||||
|
term->multi_cursor.text_color_source = MULTI_CURSOR_COLOR_PRIMARY;
|
||||||
|
term->multi_cursor.cursor_color = 0;
|
||||||
|
term->multi_cursor.text_color = 0;
|
||||||
|
|
||||||
if (!hard)
|
if (!hard)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
24
terminal.h
24
terminal.h
|
|
@ -407,6 +407,23 @@ struct colors {
|
||||||
enum which_color_theme active_theme;
|
enum which_color_theme active_theme;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Synchronized with the multi-cursor protocol specification */
|
||||||
|
enum multi_cursor_shape {
|
||||||
|
MULTI_CURSOR_SHAPE_NONE = 0,
|
||||||
|
MULTI_CURSOR_SHAPE_BLOCK = 1,
|
||||||
|
MULTI_CURSOR_SHAPE_BEAM = 2,
|
||||||
|
MULTI_CURSOR_SHAPE_UNDERLINE = 3,
|
||||||
|
MULTI_CURSOR_SHAPE_PRIMARY = 29,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Synchronized with the multi-cursor protocol specification */
|
||||||
|
enum multi_cursor_color_source {
|
||||||
|
MULTI_CURSOR_COLOR_PRIMARY = 0,
|
||||||
|
MULTI_CURSOR_COLOR_SPECIAL = 1,
|
||||||
|
MULTI_CURSOR_COLOR_RGB = 2,
|
||||||
|
MULTI_CURSOR_COLOR_256 = 5,
|
||||||
|
};
|
||||||
|
|
||||||
struct terminal {
|
struct terminal {
|
||||||
struct fdm *fdm;
|
struct fdm *fdm;
|
||||||
struct reaper *reaper;
|
struct reaper *reaper;
|
||||||
|
|
@ -834,6 +851,11 @@ struct terminal {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
pixman_region32_t active;
|
pixman_region32_t active;
|
||||||
|
enum multi_cursor_shape *shapes; /* Flattened 2-dimensional array */
|
||||||
|
enum multi_cursor_color_source cursor_color_source;
|
||||||
|
enum multi_cursor_color_source text_color_source;
|
||||||
|
uint32_t cursor_color;
|
||||||
|
uint32_t text_color;
|
||||||
} multi_cursor;
|
} multi_cursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -992,6 +1014,8 @@ void term_theme_switch_to_1(struct terminal *term);
|
||||||
void term_theme_switch_to_2(struct terminal *term);
|
void term_theme_switch_to_2(struct terminal *term);
|
||||||
void term_theme_toggle(struct terminal *term);
|
void term_theme_toggle(struct terminal *term);
|
||||||
|
|
||||||
|
void term_remove_all_multi_cursors(struct terminal *term);
|
||||||
|
|
||||||
static inline void term_reset_grapheme_state(struct terminal *term)
|
static inline void term_reset_grapheme_state(struct terminal *term)
|
||||||
{
|
{
|
||||||
#if defined(FOOT_GRAPHEME_CLUSTERING)
|
#if defined(FOOT_GRAPHEME_CLUSTERING)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue