mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-09 05:33:58 -04:00
Merge branch 'url-mode-snapshot-screen-state'
This commit is contained in:
commit
44d9b7c74f
7 changed files with 168 additions and 20 deletions
|
|
@ -7,6 +7,7 @@
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "selection.h"
|
#include "selection.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
#include "url-mode.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -14,6 +15,8 @@ cmd_scrollback_up(struct terminal *term, int rows)
|
||||||
{
|
{
|
||||||
if (term->grid == &term->alt)
|
if (term->grid == &term->alt)
|
||||||
return;
|
return;
|
||||||
|
if (urls_mode_is_active(term))
|
||||||
|
return;
|
||||||
|
|
||||||
if (term->mouse_tracking != MOUSE_NONE)
|
if (term->mouse_tracking != MOUSE_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
@ -92,6 +95,8 @@ cmd_scrollback_down(struct terminal *term, int rows)
|
||||||
{
|
{
|
||||||
if (term->grid == &term->alt)
|
if (term->grid == &term->alt)
|
||||||
return;
|
return;
|
||||||
|
if (urls_mode_is_active(term))
|
||||||
|
return;
|
||||||
|
|
||||||
if (term->mouse_tracking != MOUSE_NONE)
|
if (term->mouse_tracking != MOUSE_NONE)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
100
grid.c
100
grid.c
|
|
@ -8,9 +8,109 @@
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "sixel.h"
|
#include "sixel.h"
|
||||||
|
#include "stride.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
struct grid *
|
||||||
|
grid_snapshot(const struct grid *grid)
|
||||||
|
{
|
||||||
|
struct grid *clone = xmalloc(sizeof(*clone));
|
||||||
|
clone->num_rows = grid->num_rows;
|
||||||
|
clone->num_cols = grid->num_cols;
|
||||||
|
clone->offset = grid->offset;
|
||||||
|
clone->view = grid->view;
|
||||||
|
clone->cursor = grid->cursor;
|
||||||
|
clone->rows = xcalloc(grid->num_rows, sizeof(clone->rows[0]));
|
||||||
|
memset(&clone->scroll_damage, 0, sizeof(clone->scroll_damage));
|
||||||
|
memset(&clone->sixel_images, 0, sizeof(clone->sixel_images));
|
||||||
|
|
||||||
|
tll_foreach(grid->scroll_damage, it)
|
||||||
|
tll_push_back(clone->scroll_damage, it->item);
|
||||||
|
|
||||||
|
for (int r = 0; r < grid->num_rows; r++) {
|
||||||
|
const struct row *row = grid->rows[r];
|
||||||
|
|
||||||
|
if (row == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
struct row *clone_row = xmalloc(sizeof(*row));
|
||||||
|
clone->rows[r] = clone_row;
|
||||||
|
|
||||||
|
clone_row->cells = xmalloc(grid->num_cols * sizeof(clone_row->cells[0]));
|
||||||
|
clone_row->linebreak = row->linebreak;
|
||||||
|
clone_row->dirty = row->dirty;;
|
||||||
|
|
||||||
|
for (int c = 0; c < grid->num_cols; c++) {
|
||||||
|
clone_row->cells[c] = row->cells[c];
|
||||||
|
clone_row->cells[c].attrs.clean = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row->extra != NULL) {
|
||||||
|
const struct row_data *extra = row->extra;
|
||||||
|
struct row_data *new_extra = xcalloc(1, sizeof(*new_extra));
|
||||||
|
|
||||||
|
tll_foreach(extra->uri_ranges, it) {
|
||||||
|
struct row_uri_range range = {
|
||||||
|
.start = it->item.start,
|
||||||
|
.end = it->item.end,
|
||||||
|
.id = it->item.id,
|
||||||
|
.uri = xstrdup(it->item.uri),
|
||||||
|
};
|
||||||
|
|
||||||
|
tll_push_back(new_extra->uri_ranges, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_row->extra = new_extra;
|
||||||
|
} else
|
||||||
|
clone_row->extra = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tll_foreach(grid->sixel_images, it) {
|
||||||
|
int width = it->item.width;
|
||||||
|
int height = it->item.height;
|
||||||
|
pixman_image_t *pix = it->item.pix;
|
||||||
|
pixman_format_code_t pix_fmt = pixman_image_get_format(pix);
|
||||||
|
int stride = stride_for_format_and_width(pix_fmt, width);
|
||||||
|
|
||||||
|
size_t size = stride * height;
|
||||||
|
void *new_data = xmalloc(size);
|
||||||
|
memcpy(new_data, it->item.data, size);
|
||||||
|
|
||||||
|
pixman_image_t *new_pix = pixman_image_create_bits_no_clear(
|
||||||
|
pix_fmt, width, height, new_data, stride);
|
||||||
|
|
||||||
|
struct sixel six = {
|
||||||
|
.data = new_data,
|
||||||
|
.pix = new_pix,
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
.rows = it->item.rows,
|
||||||
|
.cols = it->item.cols,
|
||||||
|
.pos = it->item.pos,
|
||||||
|
};
|
||||||
|
|
||||||
|
tll_push_back(clone->sixel_images, six);
|
||||||
|
}
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grid_free(struct grid *grid)
|
||||||
|
{
|
||||||
|
for (int r = 0; r < grid->num_rows; r++)
|
||||||
|
grid_row_free(grid->rows[r]);
|
||||||
|
|
||||||
|
tll_foreach(grid->sixel_images, it) {
|
||||||
|
sixel_destroy(&it->item);
|
||||||
|
tll_remove(grid->sixel_images, it);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(grid->rows);
|
||||||
|
tll_free(grid->scroll_damage);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grid_swap_row(struct grid *grid, int row_a, int row_b)
|
grid_swap_row(struct grid *grid, int row_a, int row_b)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
3
grid.h
3
grid.h
|
|
@ -4,6 +4,9 @@
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "terminal.h"
|
#include "terminal.h"
|
||||||
|
|
||||||
|
struct grid *grid_snapshot(const struct grid *grid);
|
||||||
|
void grid_free(struct grid *grid);
|
||||||
|
|
||||||
void grid_swap_row(struct grid *grid, int row_a, int row_b);
|
void grid_swap_row(struct grid *grid, int row_a, int row_b);
|
||||||
struct row *grid_row_alloc(int cols, bool initialize);
|
struct row *grid_row_alloc(int cols, bool initialize);
|
||||||
void grid_row_free(struct row *row);
|
void grid_row_free(struct row *row);
|
||||||
|
|
|
||||||
16
render.c
16
render.c
|
|
@ -2675,6 +2675,12 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da
|
||||||
term->render.pending.title = false;
|
term->render.pending.title = false;
|
||||||
term->render.pending.urls = false;
|
term->render.pending.urls = false;
|
||||||
|
|
||||||
|
struct grid *original_grid = term->grid;
|
||||||
|
if (urls_mode_is_active(term)) {
|
||||||
|
xassert(term->url_grid_snapshot != NULL);
|
||||||
|
term->grid = term->url_grid_snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
if (csd && term->window->use_csd == CSD_YES) {
|
if (csd && term->window->use_csd == CSD_YES) {
|
||||||
quirk_weston_csd_on(term);
|
quirk_weston_csd_on(term);
|
||||||
render_csd(term);
|
render_csd(term);
|
||||||
|
|
@ -2697,6 +2703,8 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da
|
||||||
if (it->item.kbd_focus == term)
|
if (it->item.kbd_focus == term)
|
||||||
ime_update_cursor_rect(&it->item, term);
|
ime_update_cursor_rect(&it->item, term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
term->grid = original_grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -3127,6 +3135,12 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data)
|
||||||
term->render.refresh.urls = false;
|
term->render.refresh.urls = false;
|
||||||
|
|
||||||
if (term->window->frame_callback == NULL) {
|
if (term->window->frame_callback == NULL) {
|
||||||
|
struct grid *original_grid = term->grid;
|
||||||
|
if (urls_mode_is_active(term)) {
|
||||||
|
xassert(term->url_grid_snapshot != NULL);
|
||||||
|
term->grid = term->url_grid_snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
if (csd && term->window->use_csd == CSD_YES) {
|
if (csd && term->window->use_csd == CSD_YES) {
|
||||||
quirk_weston_csd_on(term);
|
quirk_weston_csd_on(term);
|
||||||
render_csd(term);
|
render_csd(term);
|
||||||
|
|
@ -3145,6 +3159,8 @@ fdm_hook_refresh_pending_terminals(struct fdm *fdm, void *data)
|
||||||
if (it->item.kbd_focus == term)
|
if (it->item.kbd_focus == term)
|
||||||
ime_update_cursor_rect(&it->item, term);
|
ime_update_cursor_rect(&it->item, term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
term->grid = original_grid;
|
||||||
} else {
|
} else {
|
||||||
/* Tells the frame callback to render again */
|
/* Tells the frame callback to render again */
|
||||||
term->render.pending.grid |= grid;
|
term->render.pending.grid |= grid;
|
||||||
|
|
|
||||||
21
terminal.c
21
terminal.c
|
|
@ -227,8 +227,6 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data)
|
||||||
cursor_blink_rearm_timer(term);
|
cursor_blink_rearm_timer(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
urls_reset(term);
|
|
||||||
|
|
||||||
uint8_t buf[24 * 1024];
|
uint8_t buf[24 * 1024];
|
||||||
ssize_t count = sizeof(buf);
|
ssize_t count = sizeof(buf);
|
||||||
|
|
||||||
|
|
@ -1437,15 +1435,8 @@ term_destroy(struct terminal *term)
|
||||||
mtx_unlock(&term->render.workers.lock);
|
mtx_unlock(&term->render.workers.lock);
|
||||||
|
|
||||||
free(term->vt.osc.data);
|
free(term->vt.osc.data);
|
||||||
for (int row = 0; row < term->normal.num_rows; row++)
|
grid_free(&term->normal);
|
||||||
grid_row_free(term->normal.rows[row]);
|
grid_free(&term->alt);
|
||||||
free(term->normal.rows);
|
|
||||||
for (int row = 0; row < term->alt.num_rows; row++)
|
|
||||||
grid_row_free(term->alt.rows[row]);
|
|
||||||
free(term->alt.rows);
|
|
||||||
|
|
||||||
tll_free(term->normal.scroll_damage);
|
|
||||||
tll_free(term->alt.scroll_damage);
|
|
||||||
|
|
||||||
free(term->composed);
|
free(term->composed);
|
||||||
|
|
||||||
|
|
@ -1490,14 +1481,6 @@ term_destroy(struct terminal *term)
|
||||||
tll_remove(term->ptmx_paste_buffers, it);
|
tll_remove(term->ptmx_paste_buffers, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
tll_foreach(term->normal.sixel_images, it) {
|
|
||||||
sixel_destroy(&it->item);
|
|
||||||
tll_remove(term->normal.sixel_images, it);
|
|
||||||
}
|
|
||||||
tll_foreach(term->alt.sixel_images, it) {
|
|
||||||
sixel_destroy(&it->item);
|
|
||||||
tll_remove(term->alt.sixel_images, it);
|
|
||||||
}
|
|
||||||
sixel_fini(term);
|
sixel_fini(term);
|
||||||
|
|
||||||
urls_reset(term);
|
urls_reset(term);
|
||||||
|
|
|
||||||
|
|
@ -547,9 +547,11 @@ struct terminal {
|
||||||
unsigned max_height; /* Maximum image height, in pixels */
|
unsigned max_height; /* Maximum image height, in pixels */
|
||||||
} sixel;
|
} sixel;
|
||||||
|
|
||||||
|
/* TODO: wrap in a struct */
|
||||||
url_list_t urls;
|
url_list_t urls;
|
||||||
wchar_t url_keys[5];
|
wchar_t url_keys[5];
|
||||||
bool urls_show_uri_on_jump_label;
|
bool urls_show_uri_on_jump_label;
|
||||||
|
struct grid *url_grid_snapshot;
|
||||||
|
|
||||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
41
url-mode.c
41
url-mode.c
|
|
@ -637,6 +637,28 @@ urls_render(struct terminal *term)
|
||||||
tag_cells_for_url(term, &it->item, true);
|
tag_cells_for_url(term, &it->item, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dirty the last cursor, to ensure it is erased */
|
||||||
|
{
|
||||||
|
struct row *cursor_row = term->render.last_cursor.row;
|
||||||
|
if (cursor_row != NULL) {
|
||||||
|
struct cell *cell = &cursor_row->cells[term->render.last_cursor.col];
|
||||||
|
cell->attrs.clean = 0;
|
||||||
|
cursor_row->dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
term->render.last_cursor.row = NULL;
|
||||||
|
|
||||||
|
/* Clear scroll damage, to ensure we don’t apply it twice (once on
|
||||||
|
* the snapshot:ed grid, and then later again on the real grid) */
|
||||||
|
tll_free(term->grid->scroll_damage);
|
||||||
|
|
||||||
|
/* Damage the entire view, to ensure a full screen redraw, both
|
||||||
|
* now, when entering URL mode, and later, when exiting it. */
|
||||||
|
term_damage_view(term);
|
||||||
|
|
||||||
|
/* Snapshot the current grid */
|
||||||
|
term->url_grid_snapshot = grid_snapshot(term->grid);
|
||||||
|
|
||||||
render_refresh_urls(term);
|
render_refresh_urls(term);
|
||||||
render_refresh(term);
|
render_refresh(term);
|
||||||
}
|
}
|
||||||
|
|
@ -651,8 +673,24 @@ url_destroy(struct url *url)
|
||||||
void
|
void
|
||||||
urls_reset(struct terminal *term)
|
urls_reset(struct terminal *term)
|
||||||
{
|
{
|
||||||
if (likely(tll_length(term->urls) == 0))
|
if (likely(tll_length(term->urls) == 0)) {
|
||||||
|
xassert(term->url_grid_snapshot == NULL);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
grid_free(term->url_grid_snapshot);
|
||||||
|
free(term->url_grid_snapshot);
|
||||||
|
term->url_grid_snapshot = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure “last cursor” doesn’t point to a row in the just
|
||||||
|
* free:d snapshot grid.
|
||||||
|
*
|
||||||
|
* Note that it will still be erased properly (if hasn’t already),
|
||||||
|
* since we marked the cell as dirty *before* taking the grid
|
||||||
|
* snapshot.
|
||||||
|
*/
|
||||||
|
term->render.last_cursor.row = NULL;
|
||||||
|
|
||||||
if (term->window != NULL) {
|
if (term->window != NULL) {
|
||||||
tll_foreach(term->window->urls, it) {
|
tll_foreach(term->window->urls, it) {
|
||||||
|
|
@ -669,5 +707,6 @@ urls_reset(struct terminal *term)
|
||||||
|
|
||||||
term->urls_show_uri_on_jump_label = false;
|
term->urls_show_uri_on_jump_label = false;
|
||||||
memset(term->url_keys, 0, sizeof(term->url_keys));
|
memset(term->url_keys, 0, sizeof(term->url_keys));
|
||||||
|
|
||||||
render_refresh(term);
|
render_refresh(term);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue