Graphics protocol: Fix delete by number not deleting newest image with the specified number

Fixes #8071
This commit is contained in:
Kovid Goyal 2024-11-24 10:11:34 +05:30
parent 0eaf44d33d
commit cb2e1fcd04
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
3 changed files with 25 additions and 13 deletions

View file

@ -97,6 +97,8 @@ Detailed list of changes
- Wayland: Fix an abort when a client program tries to set an invalid title containing interleaved escape codes and UTF-8 multi-byte characters (:iss:`8067`)
- Graphics protocol: Fix delete by number not deleting newest image with the specified number (:iss:`8071`)
0.37.0 [2024-10-30]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -2051,14 +2051,6 @@ id_range_filter_func(const ImageRef *ref UNUSED, Image *img, const void *data, C
}
static bool
number_filter_func(const ImageRef *ref, Image *img, const void *data, CellPixelSize cell UNUSED) {
const GraphicsCommand *g = data;
if (g->image_number && img->client_number == g->image_number) return !g->placement_id || ref->client_id == g->placement_id;
return false;
}
static bool
x_filter_func(const ImageRef *ref, Image UNUSED *img, const void *data, CellPixelSize cell UNUSED) {
if (ref->is_virtual_ref || is_cell_image(ref)) return false;
@ -2098,9 +2090,8 @@ static void
handle_delete_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c, bool *is_dirty, CellPixelSize cell) {
if (self->currently_loading.loading_for.image_id) free_load_data(&self->currently_loading);
GraphicsCommand d;
bool only_first_image = false;
switch (g->delete_action) {
#define I(u, data, func) filter_refs(self, data, g->delete_action == u, func, cell, only_first_image); *is_dirty = true; break
#define I(u, data, func) filter_refs(self, data, g->delete_action == u, func, cell, false); *is_dirty = true; break
#define D(l, u, data, func) case l: case u: I(u, data, func)
#define G(l, u, func) D(l, u, g, func)
case 0:
@ -2117,9 +2108,18 @@ handle_delete_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c
d.x_offset = c->x + 1; d.y_offset = c->y + 1;
I('C', &d, point_filter_func);
case 'n':
case 'N':
only_first_image = true;
I('N', g, number_filter_func);
case 'N': {
Image *img = img_by_client_number(self, g->image_number);
if (img) {
for (ref_map_itr ri = vt_first(&img->refs_by_internal_id); !vt_is_end(ri); ) { ImageRef *ref = ri.data->val;
if (!g->placement_id || g->placement_id == ref->client_id) {
ri = remove_ref_itr(img, ri);
self->layers_dirty = true;
} else ri = vt_next(ri);
}
if (!vt_size(&img->refs_by_internal_id) && (g->delete_action == 'N' || img->client_id == 0)) remove_image(self, img);
}
} break;
case 'f':
case 'F':
if (handle_delete_frame_command(self, g, is_dirty) != NULL) {

View file

@ -582,6 +582,16 @@ def delete(ac='N', **kw):
self.ae(s.grman.image_count, count - 1)
delete(I=1)
self.ae(s.grman.image_count, count - 2)
cn = 1117
li('abc', s=1, v=1, f=24, I=cn)
first_id = g.image_for_client_number(cn)['internal_id']
li('abc', s=1, v=1, f=24, I=cn)
second_id = g.image_for_client_number(cn)['internal_id']
self.assertNotEqual(first_id, second_id)
count = s.grman.image_count
delete(I=cn)
self.ae(g.image_for_client_number(cn)['internal_id'], first_id)
self.ae(s.grman.image_count, count - 1)
s.reset()
self.assertEqual(g.disk_cache.total_size, 0)