Add a a=q mode for querying without storing image data

This commit is contained in:
Kovid Goyal 2017-10-06 23:43:42 +05:30
parent 9e284442e8
commit 6a65f23f98
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 27 additions and 10 deletions

View File

@ -200,6 +200,13 @@ request. The message data will be a ASCII encoded string containing only
printable characters and spaces. The string will be `OK` if reading the pixel printable characters and spaces. The string will be `OK` if reading the pixel
data succeeded or an error message. data succeeded or an error message.
Sometimes, using an id is not appropriate, for example, if you do not want to
replace a previously sent image with the same id, or if you are sending a dummy
image and do not want it stored by the terminal emulator. In that case, you can
use the *query action*, set `a=q`. Then the terminal emulator will try to load
the image and respond with either OK or an error, as above, but it will not
replace an existing image with the same id, nor will it store the image.
== Display images on screen == Display images on screen
@ -258,7 +265,7 @@ take, and the default value they take when missing. All integers are 32-bit.
|=== |===
|Key | Value | Default | Description |Key | Value | Default | Description
| `a` | Single character. `(t, T, p)` | `t` | The overall action this graphics command is performing. | `a` | Single character. `(t, T, q, p)` | `t` | The overall action this graphics command is performing.
4+^.^h| Keys for image transmission 4+^.^h| Keys for image transmission

View File

@ -328,7 +328,7 @@ remove_images(GraphicsManager *self, bool(*predicate)(Image*)) {
static Image* static Image*
handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload, bool *is_dirty) { handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload, bool *is_dirty, uint32_t iid) {
#define ABRT(code, ...) { set_add_response(#code, __VA_ARGS__); self->loading_image = 0; if (img) img->data_loaded = false; return NULL; } #define ABRT(code, ...) { set_add_response(#code, __VA_ARGS__); self->loading_image = 0; if (img) img->data_loaded = false; return NULL; }
#define MAX_DATA_SZ (4 * 100000000) #define MAX_DATA_SZ (4 * 100000000)
has_add_respose = false; has_add_respose = false;
@ -340,10 +340,11 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
if (tt == 'd' && self->loading_image) init_img = false; if (tt == 'd' && self->loading_image) init_img = false;
if (init_img) { if (init_img) {
self->last_init_graphics_command = *g; self->last_init_graphics_command = *g;
self->last_init_graphics_command.id = iid;
self->loading_image = 0; self->loading_image = 0;
if (g->data_width > 10000 || g->data_height > 10000) ABRT(EINVAL, "Image too large"); if (g->data_width > 10000 || g->data_height > 10000) ABRT(EINVAL, "Image too large");
remove_images(self, add_trim_predicate); remove_images(self, add_trim_predicate);
img = find_or_create_image(self, g->id, &existing); img = find_or_create_image(self, iid, &existing);
if (existing) { if (existing) {
free_load_data(&img->load_data); free_load_data(&img->load_data);
img->data_loaded = false; img->data_loaded = false;
@ -352,7 +353,7 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
self->layers_dirty = true; self->layers_dirty = true;
} else { } else {
img->internal_id = internal_id_counter++; img->internal_id = internal_id_counter++;
img->client_id = g->id; img->client_id = iid;
} }
img->width = g->data_width; img->height = g->data_height; img->width = g->data_width; img->height = g->data_height;
switch(fmt) { switch(fmt) {
@ -486,14 +487,14 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
} }
static inline const char* static inline const char*
create_add_response(GraphicsManager UNUSED *self, const GraphicsCommand *g, bool data_loaded) { create_add_response(GraphicsManager UNUSED *self, bool data_loaded, uint32_t iid) {
static char rbuf[sizeof(add_response)/sizeof(add_response[0])]; static char rbuf[sizeof(add_response)/sizeof(add_response[0])];
if (g->id) { if (iid) {
if (!has_add_respose) { if (!has_add_respose) {
if (!data_loaded) return NULL; if (!data_loaded) return NULL;
snprintf(add_response, 10, "OK"); snprintf(add_response, 10, "OK");
} }
snprintf(rbuf, sizeof(rbuf)/sizeof(rbuf[0]) - 1, "\033_Gi=%u;%s\033\\", g->id, add_response); snprintf(rbuf, sizeof(rbuf)/sizeof(rbuf[0]) - 1, "\033_Gi=%u;%s\033\\", iid, add_response);
return rbuf; return rbuf;
} }
return NULL; return NULL;
@ -726,14 +727,19 @@ const char*
grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload, Cursor *c, bool *is_dirty) { grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload, Cursor *c, bool *is_dirty) {
Image *image; Image *image;
const char *ret = NULL; const char *ret = NULL;
uint32_t iid, q_iid;
switch(g->action) { switch(g->action) {
case 0: case 0:
case 't': case 't':
case 'T': case 'T':
image = handle_add_command(self, g, payload, is_dirty); case 'q':
ret = create_add_response(self, &self->last_init_graphics_command, image != NULL); iid = g->id;
if (g->action == 'q') { q_iid = iid; iid = 0; if (!q_iid) { REPORT_ERROR("Query graphics command without image id"); break; } }
image = handle_add_command(self, g, payload, is_dirty, iid);
ret = create_add_response(self, image != NULL, g->action == 'q' ? q_iid: self->last_init_graphics_command.id);
if (self->last_init_graphics_command.action == 'T' && image && image->data_loaded) handle_put_command(self, &self->last_init_graphics_command, c, is_dirty, image); if (self->last_init_graphics_command.action == 'T' && image && image->data_loaded) handle_put_command(self, &self->last_init_graphics_command, c, is_dirty, image);
if (g->action == 'q') remove_images(self, add_trim_predicate);
break; break;
case 'p': case 'p':
if (!g->id) { if (!g->id) {
@ -741,7 +747,7 @@ grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint
break; break;
} }
handle_put_command(self, g, c, is_dirty, NULL); handle_put_command(self, g, c, is_dirty, NULL);
ret = create_add_response(self, g, true); ret = create_add_response(self, true, g->id);
break; break;
default: default:
REPORT_ERROR("Unknown graphics command action: %c", g->action); REPORT_ERROR("Unknown graphics command action: %c", g->action);

View File

@ -124,6 +124,10 @@ class TestGraphics(BaseTest):
def test_load_images(self): def test_load_images(self):
s, g, l, sl = load_helpers(self) s, g, l, sl = load_helpers(self)
# Test load query
self.ae(l('abcd', s=1, v=1, a='q'), 'OK')
self.ae(g.image_count, 0)
# Test simple load # Test simple load
for f in 32, 24: for f in 32, 24:
p = 'abc' + ('d' if f == 32 else '') p = 'abc' + ('d' if f == 32 else '')