Implement control code for deleting images

This commit is contained in:
Kovid Goyal
2017-10-08 22:51:00 +05:30
parent 3f9f5ae076
commit 747f7b076d
6 changed files with 156 additions and 14 deletions
+73 -5
View File
@@ -561,6 +561,7 @@ handle_put_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c, b
}
c->x += num_cols; c->y += num_rows - 1;
ref->effective_num_rows = num_rows;
ref->effective_num_cols = num_cols;
}
static int
@@ -630,7 +631,7 @@ grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float scree
// Image lifetime/scrolling {{{
static inline void
filter_refs(GraphicsManager *self, const void* data, bool (*filter_func)(ImageRef*, Image*, const void*)) {
filter_refs(GraphicsManager *self, const void* data, bool free_images, bool (*filter_func)(ImageRef*, Image*, const void*)) {
Image *img; ImageRef *ref;
size_t i, j;
@@ -643,7 +644,7 @@ filter_refs(GraphicsManager *self, const void* data, bool (*filter_func)(ImageRe
remove_from_array(img->refs, sizeof(ImageRef), j, img->refcnt--);
}
}
if (img->refcnt == 0) {
if (img->refcnt == 0 && (free_images || img->client_id == 0)) {
free_image(img);
remove_from_array(self->images, sizeof(Image), i, self->image_count--);
}
@@ -702,7 +703,7 @@ scroll_filter_margins_func(ImageRef* ref, Image* img, const void* data) {
void
grman_scroll_images(GraphicsManager *self, const ScrollData *data) {
filter_refs(self, data, data->has_margins ? scroll_filter_margins_func : scroll_filter_func);
filter_refs(self, data, true, data->has_margins ? scroll_filter_margins_func : scroll_filter_func);
}
static inline bool
@@ -712,7 +713,71 @@ clear_filter_func(ImageRef *ref, Image UNUSED *img, const void UNUSED *data) {
void
grman_clear(GraphicsManager *self) {
filter_refs(self, NULL, clear_filter_func);
filter_refs(self, NULL, true, clear_filter_func);
}
static inline bool
id_filter_func(ImageRef UNUSED *ref, Image *img, const void *data) {
uint32_t iid = *(uint32_t*)data;
return img->client_id == iid;
}
static inline bool
x_filter_func(ImageRef *ref, Image UNUSED *img, const void *data) {
const GraphicsCommand *g = data;
return ref->start_column <= (int32_t)g->x_offset - 1 && ((int32_t)g->x_offset - 1) < ((int32_t)(ref->start_column + ref->effective_num_cols));
}
static inline bool
y_filter_func(ImageRef *ref, Image UNUSED *img, const void *data) {
const GraphicsCommand *g = data;
return ref->start_row <= (int32_t)g->y_offset - 1 && ((int32_t)(g->y_offset - 1 < ref->start_row + ref->effective_num_rows));
}
static inline bool
z_filter_func(ImageRef *ref, Image UNUSED *img, const void *data) {
const GraphicsCommand *g = data;
return ref->z_index == g->z_index;
}
static inline bool
point_filter_func(ImageRef *ref, Image *img, const void *data) {
return x_filter_func(ref, img, data) && y_filter_func(ref, img, data);
}
static inline bool
point3d_filter_func(ImageRef *ref, Image *img, const void *data) {
return z_filter_func(ref, img, data) && point_filter_func(ref, img, data);
}
static void
handle_delete_command(GraphicsManager *self, const GraphicsCommand *g, Cursor *c, bool *is_dirty) {
static GraphicsCommand d;
switch (g->delete_action) {
#define I(u, data, func) filter_refs(self, data, g->delete_action == u, func); *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:
D('a', 'A', NULL, clear_filter_func);
D('i', 'I', &g->id, id_filter_func);
G('p', 'P', point_filter_func);
G('q', 'Q', point3d_filter_func);
G('x', 'X', x_filter_func);
G('y', 'Y', y_filter_func);
G('z', 'Z', z_filter_func);
case 'c':
case 'C':
d.x_offset = c->x + 1; d.y_offset = c->y + 1;
I('C', &d, point_filter_func);
default:
REPORT_ERROR("Unknown graphics command delete action: %c", g->delete_action);
break;
#undef G
#undef D
#undef I
}
}
// }}}
@@ -737,12 +802,15 @@ grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint
break;
case 'p':
if (!g->id) {
REPORT_ERROR("%s", "Put graphics command without image id");
REPORT_ERROR("Put graphics command without image id");
break;
}
handle_put_command(self, g, c, is_dirty, NULL);
ret = create_add_response(self, true, g->id);
break;
case 'd':
handle_delete_command(self, g, c, is_dirty);
break;
default:
REPORT_ERROR("Unknown graphics command action: %c", g->action);
break;
+2 -2
View File
@@ -8,7 +8,7 @@
#include "data-types.h"
typedef struct {
unsigned char action, transmission_type, compressed;
unsigned char action, transmission_type, compressed, delete_action;
uint32_t format, more, id, data_sz, data_offset;
uint32_t width, height, x_offset, y_offset, data_height, data_width, num_cells, num_lines, cell_x_offset, cell_y_offset;
int32_t z_index;
@@ -34,7 +34,7 @@ typedef struct {
typedef struct {
uint32_t src_width, src_height, src_x, src_y;
uint32_t cell_x_offset, cell_y_offset, num_cols, num_rows, effective_num_rows;
uint32_t cell_x_offset, cell_y_offset, num_cols, num_rows, effective_num_rows, effective_num_cols;
int32_t z_index;
int32_t start_row, start_column;
ImageRect src_rect;
+5 -4
View File
@@ -540,6 +540,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
enum GR_STATES state = KEY, value_state = FLAG;
enum KEYS {
action='a',
delete_action='d',
transmission_type='t',
compressed='o',
format = 'f',
@@ -577,7 +578,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
switch(key) {
#define KS(n, vs) case n: state = EQUAL; value_state = vs; break
#define U(x) KS(x, UINT)
KS(action, FLAG); KS(transmission_type, FLAG); KS(compressed, FLAG); KS(z_index, INT);
KS(action, FLAG); KS(delete_action, FLAG); KS(transmission_type, FLAG); KS(compressed, FLAG); KS(z_index, INT);
U(format); U(more); U(id); U(data_sz); U(data_offset); U(width); U(height); U(x_offset); U(y_offset); U(data_height); U(data_width); U(num_cells); U(num_lines); U(cell_x_offset); U(cell_y_offset);
#undef U
#undef KS
@@ -598,7 +599,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
case FLAG:
switch(key) {
#define F(a) case a: g.a = screen->parser_buf[pos++] & 0xff; break
F(action); F(transmission_type); F(compressed);
F(action); F(delete_action); F(transmission_type); F(compressed);
default:
break;
}
@@ -675,8 +676,8 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) {
#define A(x) #x, g.x
#define U(x) #x, (unsigned int)(g.x)
#define I(x) #x, (int)(g.x)
REPORT_VA_COMMAND("s {sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI si} y#", "graphics_command",
A(action), A(transmission_type), A(compressed),
REPORT_VA_COMMAND("s {sc sc sc sc sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI sI si} y#", "graphics_command",
A(action), A(delete_action), A(transmission_type), A(compressed),
U(format), U(more), U(id), U(data_sz), U(data_offset),
U(width), U(height), U(x_offset), U(y_offset), U(data_height), U(data_width), U(num_cells), U(num_lines), U(cell_x_offset), U(cell_y_offset),
U(payload_sz), I(z_index),