2019-08-04 16:52:45 +00:00
|
|
|
#include <uthash.h>
|
|
|
|
#include <xcb/xcb.h>
|
|
|
|
|
2019-08-09 23:56:04 +00:00
|
|
|
#include "backend/backend.h"
|
2019-08-04 16:52:45 +00:00
|
|
|
#include "backend/backend_common.h"
|
|
|
|
#include "common.h"
|
|
|
|
#include "compiler.h"
|
2019-08-09 23:56:04 +00:00
|
|
|
#include "config.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "region.h"
|
|
|
|
#include "types.h"
|
2019-08-04 16:52:45 +00:00
|
|
|
#include "uthash_extra.h"
|
|
|
|
#include "utils.h"
|
2019-08-09 23:56:04 +00:00
|
|
|
#include "x.h"
|
2019-08-04 16:52:45 +00:00
|
|
|
|
|
|
|
struct dummy_image {
|
|
|
|
xcb_pixmap_t pixmap;
|
|
|
|
bool transparent;
|
2019-09-23 19:02:30 +00:00
|
|
|
int *refcount;
|
2023-06-12 20:41:25 +00:00
|
|
|
bool owned;
|
2019-08-04 16:52:45 +00:00
|
|
|
UT_hash_handle hh;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct dummy_data {
|
|
|
|
struct backend_base base;
|
|
|
|
struct dummy_image *images;
|
2022-08-24 06:35:49 +00:00
|
|
|
|
|
|
|
struct backend_image mask;
|
2019-08-04 16:52:45 +00:00
|
|
|
};
|
|
|
|
|
2023-08-02 22:04:56 +00:00
|
|
|
struct backend_base *dummy_init(session_t *ps attr_unused, xcb_window_t target attr_unused) {
|
2019-08-09 22:33:01 +00:00
|
|
|
auto ret = (struct backend_base *)ccalloc(1, struct dummy_data);
|
2023-06-29 04:39:36 +00:00
|
|
|
ret->c = &ps->c;
|
2019-08-09 22:33:01 +00:00
|
|
|
ret->loop = ps->loop;
|
|
|
|
ret->busy = false;
|
|
|
|
return ret;
|
2019-08-04 16:52:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dummy_deinit(struct backend_base *data) {
|
|
|
|
auto dummy = (struct dummy_data *)data;
|
|
|
|
HASH_ITER2(dummy->images, img) {
|
|
|
|
log_warn("Backend image for pixmap %#010x is not freed", img->pixmap);
|
|
|
|
HASH_DEL(dummy->images, img);
|
2019-09-23 19:02:30 +00:00
|
|
|
free(img->refcount);
|
2023-06-12 20:41:25 +00:00
|
|
|
if (img->owned) {
|
2023-06-29 04:39:36 +00:00
|
|
|
xcb_free_pixmap(data->c->c, img->pixmap);
|
2023-06-12 20:41:25 +00:00
|
|
|
}
|
2019-08-04 16:52:45 +00:00
|
|
|
free(img);
|
|
|
|
}
|
|
|
|
free(dummy);
|
|
|
|
}
|
|
|
|
|
2019-09-23 19:02:30 +00:00
|
|
|
static void dummy_check_image(struct backend_base *base, const struct dummy_image *img) {
|
2019-08-04 16:52:45 +00:00
|
|
|
auto dummy = (struct dummy_data *)base;
|
2022-08-24 06:35:49 +00:00
|
|
|
if (img == (struct dummy_image *)&dummy->mask) {
|
|
|
|
return;
|
|
|
|
}
|
2019-08-04 16:52:45 +00:00
|
|
|
struct dummy_image *tmp = NULL;
|
|
|
|
HASH_FIND_INT(dummy->images, &img->pixmap, tmp);
|
|
|
|
if (!tmp) {
|
2019-09-23 19:02:30 +00:00
|
|
|
log_warn("Using an invalid (possibly freed) image");
|
|
|
|
assert(false);
|
2019-08-04 16:52:45 +00:00
|
|
|
}
|
2019-09-23 19:02:30 +00:00
|
|
|
assert(*tmp->refcount > 0);
|
|
|
|
}
|
|
|
|
|
2022-08-24 06:35:49 +00:00
|
|
|
void dummy_compose(struct backend_base *base, void *image, coord_t dst attr_unused,
|
|
|
|
void *mask attr_unused, coord_t mask_dst attr_unused,
|
|
|
|
const region_t *reg_paint attr_unused,
|
2019-09-23 19:02:30 +00:00
|
|
|
const region_t *reg_visible attr_unused) {
|
2022-08-24 06:35:49 +00:00
|
|
|
auto dummy attr_unused = (struct dummy_data *)base;
|
2019-09-23 19:02:30 +00:00
|
|
|
dummy_check_image(base, image);
|
2022-08-24 06:35:49 +00:00
|
|
|
assert(mask == NULL || mask == &dummy->mask);
|
2019-08-04 16:52:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void dummy_fill(struct backend_base *backend_data attr_unused, struct color c attr_unused,
|
|
|
|
const region_t *clip attr_unused) {
|
|
|
|
}
|
|
|
|
|
|
|
|
bool dummy_blur(struct backend_base *backend_data attr_unused, double opacity attr_unused,
|
2022-08-24 07:35:24 +00:00
|
|
|
void *blur_ctx attr_unused, void *mask attr_unused,
|
|
|
|
coord_t mask_dst attr_unused, const region_t *reg_blur attr_unused,
|
2019-08-04 16:52:45 +00:00
|
|
|
const region_t *reg_visible attr_unused) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *dummy_bind_pixmap(struct backend_base *base, xcb_pixmap_t pixmap,
|
2023-06-12 20:41:25 +00:00
|
|
|
struct xvisual_info fmt, bool owned) {
|
2019-08-04 16:52:45 +00:00
|
|
|
auto dummy = (struct dummy_data *)base;
|
|
|
|
struct dummy_image *img = NULL;
|
|
|
|
HASH_FIND_INT(dummy->images, &pixmap, img);
|
|
|
|
if (img) {
|
2019-09-23 19:02:30 +00:00
|
|
|
(*img->refcount)++;
|
2019-08-04 16:52:45 +00:00
|
|
|
return img;
|
|
|
|
}
|
|
|
|
|
|
|
|
img = ccalloc(1, struct dummy_image);
|
|
|
|
img->pixmap = pixmap;
|
|
|
|
img->transparent = fmt.alpha_size != 0;
|
2019-09-23 19:02:30 +00:00
|
|
|
img->refcount = ccalloc(1, int);
|
|
|
|
*img->refcount = 1;
|
2023-06-12 20:41:25 +00:00
|
|
|
img->owned = owned;
|
2019-08-04 16:52:45 +00:00
|
|
|
|
|
|
|
HASH_ADD_INT(dummy->images, pixmap, img);
|
|
|
|
return (void *)img;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dummy_release_image(backend_t *base, void *image) {
|
|
|
|
auto dummy = (struct dummy_data *)base;
|
2022-08-24 06:35:49 +00:00
|
|
|
if (image == &dummy->mask) {
|
|
|
|
return;
|
|
|
|
}
|
2019-08-04 16:52:45 +00:00
|
|
|
auto img = (struct dummy_image *)image;
|
2019-09-23 19:02:30 +00:00
|
|
|
assert(*img->refcount > 0);
|
|
|
|
(*img->refcount)--;
|
|
|
|
if (*img->refcount == 0) {
|
2019-08-04 16:52:45 +00:00
|
|
|
HASH_DEL(dummy->images, img);
|
2019-09-23 19:02:30 +00:00
|
|
|
free(img->refcount);
|
2023-06-12 20:41:25 +00:00
|
|
|
if (img->owned) {
|
2023-06-29 04:39:36 +00:00
|
|
|
xcb_free_pixmap(base->c->c, img->pixmap);
|
2023-06-12 20:41:25 +00:00
|
|
|
}
|
2019-08-04 16:52:45 +00:00
|
|
|
free(img);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool dummy_is_image_transparent(struct backend_base *base, void *image) {
|
|
|
|
auto img = (struct dummy_image *)image;
|
2019-09-23 19:02:30 +00:00
|
|
|
dummy_check_image(base, img);
|
2019-08-04 16:52:45 +00:00
|
|
|
return img->transparent;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dummy_buffer_age(struct backend_base *base attr_unused) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2019-09-23 19:02:30 +00:00
|
|
|
bool dummy_image_op(struct backend_base *base, enum image_operations op attr_unused,
|
|
|
|
void *image, const region_t *reg_op attr_unused,
|
2019-08-04 16:52:45 +00:00
|
|
|
const region_t *reg_visible attr_unused, void *args attr_unused) {
|
2019-09-23 19:02:30 +00:00
|
|
|
dummy_check_image(base, image);
|
2019-08-04 16:52:45 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-08-24 06:35:49 +00:00
|
|
|
void *dummy_make_mask(struct backend_base *base, geometry_t size attr_unused,
|
|
|
|
const region_t *reg attr_unused) {
|
|
|
|
return &(((struct dummy_data *)base)->mask);
|
|
|
|
}
|
|
|
|
|
2021-06-14 02:22:13 +00:00
|
|
|
bool dummy_set_image_property(struct backend_base *base, enum image_properties prop attr_unused,
|
|
|
|
void *image, void *arg attr_unused) {
|
|
|
|
dummy_check_image(base, image);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-06-14 00:51:09 +00:00
|
|
|
void *dummy_clone_image(struct backend_base *base, const void *image,
|
|
|
|
const region_t *reg_visible attr_unused) {
|
2019-09-23 19:02:30 +00:00
|
|
|
auto img = (const struct dummy_image *)image;
|
|
|
|
dummy_check_image(base, img);
|
|
|
|
(*img->refcount)++;
|
|
|
|
return (void *)img;
|
2019-08-04 16:52:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void *dummy_create_blur_context(struct backend_base *base attr_unused,
|
|
|
|
enum blur_method method attr_unused, void *args attr_unused) {
|
|
|
|
static int dummy_context;
|
|
|
|
return &dummy_context;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dummy_destroy_blur_context(struct backend_base *base attr_unused, void *ctx attr_unused) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void dummy_get_blur_size(void *ctx attr_unused, int *width, int *height) {
|
2023-06-12 20:11:20 +00:00
|
|
|
// These numbers are arbitrary, to make sure the resize_region code path is
|
2019-08-04 16:52:45 +00:00
|
|
|
// covered.
|
|
|
|
*width = 5;
|
|
|
|
*height = 5;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct backend_operations dummy_ops = {
|
|
|
|
.init = dummy_init,
|
|
|
|
.deinit = dummy_deinit,
|
|
|
|
.compose = dummy_compose,
|
|
|
|
.fill = dummy_fill,
|
|
|
|
.blur = dummy_blur,
|
|
|
|
.bind_pixmap = dummy_bind_pixmap,
|
2022-08-25 04:21:19 +00:00
|
|
|
.create_shadow_context = default_create_shadow_context,
|
|
|
|
.destroy_shadow_context = default_destroy_shadow_context,
|
2023-08-02 22:38:34 +00:00
|
|
|
.render_shadow = default_render_shadow,
|
2022-08-24 06:35:49 +00:00
|
|
|
.make_mask = dummy_make_mask,
|
2019-08-04 16:52:45 +00:00
|
|
|
.release_image = dummy_release_image,
|
|
|
|
.is_image_transparent = dummy_is_image_transparent,
|
|
|
|
.buffer_age = dummy_buffer_age,
|
|
|
|
.max_buffer_age = 5,
|
|
|
|
|
|
|
|
.image_op = dummy_image_op,
|
2021-06-14 00:51:09 +00:00
|
|
|
.clone_image = dummy_clone_image,
|
2021-06-14 02:22:13 +00:00
|
|
|
.set_image_property = dummy_set_image_property,
|
2019-08-04 16:52:45 +00:00
|
|
|
.create_blur_context = dummy_create_blur_context,
|
|
|
|
.destroy_blur_context = dummy_destroy_blur_context,
|
|
|
|
.get_blur_size = dummy_get_blur_size,
|
|
|
|
|
|
|
|
};
|