Use different kitty nonces for different runs

If we always start with kitty graphics id 1, successive
runs of ncplayer -bpixel -k will erase any previously-
printed graphics. Initialize it with random() in
sprite_init(). Break graphics erasure out from sprite_init()
into new interface sprite_clear_all(), defined only for kitty.
The latter is now guarded by NCOPTION_NO_CLEAR_BITMAPS.
Closes #1578.
This commit is contained in:
nick black 2021-05-03 01:42:31 -04:00
parent a2b5a6dc03
commit a19e6a52de
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
5 changed files with 26 additions and 16 deletions

View File

@ -457,7 +457,6 @@ typedef struct tinfo {
pthread_mutex_t pixel_query; // only query for pixel support once
int color_registers; // sixel color registers (post pixel_query_done)
int sixel_maxx, sixel_maxy; // sixel size maxima (post pixel_query_done)
int sprixelnonce; // next sprixel id
int (*pixel_destroy)(const struct notcurses* nc, const struct ncpile* p, FILE* out, sprixel* s);
// wipe out a cell's worth of pixels from within a sprixel. for sixel, this
// means leaving out the pixels (and likely resizes the string). for kitty,
@ -466,9 +465,10 @@ typedef struct tinfo {
// perform the inverse of pixel_wipe, restoring an annihilated sprixcell.
int (*pixel_rebuild)(sprixel* s, int y, int x, uint8_t* auxvec);
int (*pixel_remove)(int id, FILE* out); // kitty only, issue actual delete command
int (*pixel_init)(int fd); // called when support is detected
int (*pixel_init)(int fd); // called when support is detected
int (*pixel_draw)(const struct ncpile* p, sprixel* s, FILE* out);
int (*pixel_shutdown)(int fd); // called during context shutdown
int (*pixel_shutdown)(int fd); // called during context shutdown
int (*pixel_clear_all)(int fd); // called during startup, kitty only
int sprixel_scale_height; // sprixel must be a multiple of this many rows
bool bitmap_supported; // do we support bitmaps (post pixel_query_done)?
bool sprixel_cursor_hack; // do sprixels reset the cursor? (mlterm)
@ -963,9 +963,10 @@ int sprixel_load(sprixel* spx, char* s, int bytes, int pixy, int pixx, int parse
int sixel_destroy(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s);
int kitty_destroy(const notcurses* nc, const ncpile* p, FILE* out, sprixel* s);
int kitty_remove(int id, FILE* out);
int kitty_init(int fd);
int kitty_clear_all(int fd);
int sixel_init(int fd);
int sprite_init(const notcurses* nc);
int sprite_init(const tinfo* t, int fd);
int sprite_clear_all(const tinfo* t, int fd);
int kitty_shutdown(int fd);
int sixel_shutdown(int fd);
sprixel* sprixel_by_id(const ncpile* n, uint32_t id);

View File

@ -614,7 +614,8 @@ int kitty_draw(const ncpile* p, sprixel* s, FILE* out){
}
// clears all kitty bitmaps
int kitty_init(int fd){
int kitty_clear_all(int fd){
//fprintf(stderr, "KITTY UNIVERSAL ERASE\n");
return tty_emit("\e_Ga=d\e\\", fd);
}

View File

@ -1081,7 +1081,7 @@ notcurses* notcurses_core_init(const notcurses_options* opts, FILE* outfp){
if(ret->ttyfd >= 0){
reset_term_attributes(ret);
if(!(opts->flags & NCOPTION_NO_CLEAR_BITMAPS)){
if(sprite_init(ret)){
if(sprite_clear_all(&ret->tcache, ret->ttyfd)){
free_plane(ret->stdplane);
goto err;
}

View File

@ -194,11 +194,19 @@ int sprite_wipe(const notcurses* nc, sprixel* s, int ycell, int xcell){
return r;
}
int sprite_init(const notcurses* nc){
if(!nc->tcache.pixel_init){
int sprite_clear_all(const tinfo* t, int fd){
if(t->pixel_clear_all == NULL){
return 0;
}
return nc->tcache.pixel_init(nc->ttyfd);
return t->pixel_clear_all(fd);
}
int sprite_init(const tinfo* t, int fd){
sprixelid_nonce = random() % 0xffffffu;
if(t->pixel_init == NULL){
return 0;
}
return t->pixel_init(fd);
}
uint8_t* sprixel_auxiliary_vector(const sprixel* s){

View File

@ -20,16 +20,17 @@ setup_sixel_bitmaps(tinfo* ti){
}
static inline void
setup_kitty_bitmaps(tinfo* ti){
setup_kitty_bitmaps(tinfo* ti, int fd){
ti->pixel_wipe = kitty_wipe;
ti->pixel_destroy = kitty_destroy;
ti->pixel_init = kitty_init;
ti->pixel_remove = kitty_remove;
ti->pixel_draw = kitty_draw;
ti->pixel_shutdown = kitty_shutdown;
ti->sprixel_scale_height = 1;
ti->pixel_rebuild = kitty_rebuild;
ti->pixel_clear_all = kitty_clear_all;
set_pixel_blitter(kitty_blit);
sprite_init(ti, fd);
}
static bool
@ -76,7 +77,7 @@ int terminfostr(char** gseq, const char* name){
// Qui si convien lasciare ogne sospetto; ogne viltà convien che qui sia morta.
static int
apply_term_heuristics(tinfo* ti, const char* termname){
apply_term_heuristics(tinfo* ti, const char* termname, int fd){
if(!termname){
// setupterm interprets a missing/empty TERM variable as the special value “unknown”.
termname = "unknown";
@ -91,7 +92,7 @@ apply_term_heuristics(tinfo* ti, const char* termname){
ti->quadrants = true;
ti->pixel_query_done = true;
ti->bitmap_supported = true;
setup_kitty_bitmaps(ti);
setup_kitty_bitmaps(ti, fd);
}else if(strstr(termname, "alacritty")){
ti->alacritty_sixel_hack = true;
ti->quadrants = true;
@ -249,10 +250,9 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname, unsigned utf8)
}
pthread_mutex_init(&ti->pixel_query, NULL);
ti->pixel_query_done = false;
if(apply_term_heuristics(ti, termname)){
if(apply_term_heuristics(ti, termname, fd)){
return -1;
}
ti->sprixelnonce = 1;
return 0;
}