Graphics protocol: Fix suppression of responses not working for chunked transmission

Now the starting escape codes q value is used unless the last escape
code specifies a non-zero q value of its own. Fixes #3375
This commit is contained in:
Kovid Goyal 2021-03-10 09:58:49 +05:30
parent eb42edff09
commit 9fdaef1da6
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 38 additions and 6 deletions

View File

@ -83,6 +83,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
- hints kitten: When using the linenumber action with a background action,
preserve the working directory (:iss:`3352`)
- Graphics protocol: Fix suppression of responses not working for chunked
transmission (:iss:`3375`)
0.19.3 [2020-12-19]
-------------------

View File

@ -269,7 +269,7 @@ sequence of escape codes to the terminal emulator::
<ESC>_Gm=0;<encoded pixel data last chunk><ESC>\
Note that only the first escape code needs to have the full set of control
codes such as width, height, format etc. Subsequent chunks must have
codes such as width, height, format etc. Subsequent chunks **must** have
only the ``m`` key. The client **must** finish sending all chunks for a single image
before sending any other graphics related escape codes. Note that the cursor
position used to display the image **must** be the position when the final chunk is

View File

@ -1508,7 +1508,7 @@ grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint
Image *image = handle_add_command(self, g, payload, is_dirty, iid);
if (!self->currently_loading.loading_for.image_id) free_load_data(&self->currently_loading);
GraphicsCommand *lg = &self->currently_loading.start_command;
lg->quiet = g->quiet;
if (g->quiet) lg->quiet = g->quiet;
if (is_query) ret = finish_command_response(&(const GraphicsCommand){.id=q_iid, .quiet=g->quiet}, image != NULL);
else ret = finish_command_response(lg, image != NULL);
if (lg->action == 'T' && image && image->root_frame_data_loaded) handle_put_command(self, lg, c, is_dirty, image, cell);
@ -1534,7 +1534,8 @@ grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint
if (ag.action == 'f') {
img = handle_animation_frame_load_command(self, &ag, img, payload, is_dirty);
if (!self->currently_loading.loading_for.image_id) free_load_data(&self->currently_loading);
ag.quiet = g->quiet;
if (g->quiet) ag.quiet = g->quiet;
else ag.quiet = self->currently_loading.start_command.quiet;
ret = finish_command_response(&ag, img != NULL);
} else if (ag.action == 'a') {
handle_animation_control_command(self, is_dirty, &ag, img);

View File

@ -286,13 +286,43 @@ class TestGraphics(BaseTest):
dc.remove_from_ram(clear_predicate)
self.assertEqual(dc.num_cached_in_ram(), 0)
def test_suppressing_gr_command_responses(self):
s, g, l, sl = load_helpers(self)
self.ae(l('abcd', s=10, v=10, q=1), 'ENODATA:Insufficient image data: 4 < 400')
self.ae(l('abcd', s=10, v=10, q=2), None)
self.assertIsNone(l('abcd', s=1, v=1, a='q', q=1))
# Test chunked load
self.assertIsNone(l('abcd', s=2, v=2, m=1, q=1))
self.assertIsNone(l('efgh', m=1))
self.assertIsNone(l('ijkl', m=1))
self.assertIsNone(l('mnop', m=0))
# errors
self.assertIsNone(l('abcd', s=2, v=2, m=1, q=1))
self.ae(l('mnop', m=0), 'ENODATA:Insufficient image data: 8 < 16')
self.assertIsNone(l('abcd', s=2, v=2, m=1, q=2))
self.assertIsNone(l('mnop', m=0))
# frames
s = self.create_screen()
li = make_send_command(s)
self.assertEqual(li().code, 'ENOENT')
self.assertIsNone(li(q=2))
self.assertIsNone(li(a='t', q=1))
self.assertIsNone(li(payload='2' * 12, z=77, m=1, q=1))
self.assertIsNone(li(payload='2' * 12, m=1))
self.assertIsNone(li(payload='2' * 12))
self.assertIsNone(li(payload='2' * 12, z=77, m=1, q=1))
self.ae(li(payload='2' * 12).code, 'ENODATA')
self.assertIsNone(li(payload='2' * 12, z=77, m=1, q=2))
self.assertIsNone(li(payload='2' * 12))
def test_load_images(self):
s, g, l, sl = load_helpers(self)
self.assertEqual(g.disk_cache.total_size, 0)
# Test load query
self.ae(l('abcd', s=1, v=1, a='q'), 'OK')
self.assertIsNone(l('abcd', s=1, v=1, a='q', q=1))
self.ae(g.image_count, 0)
# Test simple load
@ -308,8 +338,6 @@ class TestGraphics(BaseTest):
self.ae(l('mnop', m=0), 'OK')
img = g.image_for_client_id(1)
self.ae(img['data'], b'abcdefghijklmnop')
self.ae(l('abcd', s=10, v=10, q=1), 'ENODATA:Insufficient image data: 4 < 400')
self.ae(l('abcd', s=10, v=10, q=2), None)
# Test compression
random_data = byte_block(3 * 1024)