1 #include <assert.h>
2 #include <pixman.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <wayland-server-core.h>
6 #include <wlr/types/wlr_region.h>
7
region_add(struct wl_client * client,struct wl_resource * resource,int32_t x,int32_t y,int32_t width,int32_t height)8 static void region_add(struct wl_client *client, struct wl_resource *resource,
9 int32_t x, int32_t y, int32_t width, int32_t height) {
10 pixman_region32_t *region = wlr_region_from_resource(resource);
11 pixman_region32_union_rect(region, region, x, y, width, height);
12 }
13
region_subtract(struct wl_client * client,struct wl_resource * resource,int32_t x,int32_t y,int32_t width,int32_t height)14 static void region_subtract(struct wl_client *client, struct wl_resource *resource,
15 int32_t x, int32_t y, int32_t width, int32_t height) {
16 pixman_region32_t *region = wlr_region_from_resource(resource);
17 pixman_region32_union_rect(region, region, x, y, width, height);
18
19 pixman_region32_t rect;
20 pixman_region32_init_rect(&rect, x, y, width, height);
21 pixman_region32_subtract(region, region, &rect);
22 pixman_region32_fini(&rect);
23 }
24
region_destroy(struct wl_client * client,struct wl_resource * resource)25 static void region_destroy(struct wl_client *client, struct wl_resource *resource) {
26 wl_resource_destroy(resource);
27 }
28
29 static const struct wl_region_interface region_impl = {
30 .destroy = region_destroy,
31 .add = region_add,
32 .subtract = region_subtract,
33 };
34
region_handle_resource_destroy(struct wl_resource * resource)35 static void region_handle_resource_destroy(struct wl_resource *resource) {
36 pixman_region32_t *reg = wlr_region_from_resource(resource);
37
38 wl_list_remove(wl_resource_get_link(resource));
39
40 pixman_region32_fini(reg);
41 free(reg);
42 }
43
wlr_region_create(struct wl_client * client,uint32_t version,uint32_t id,struct wl_list * resource_list)44 struct wl_resource *wlr_region_create(struct wl_client *client,
45 uint32_t version, uint32_t id, struct wl_list *resource_list) {
46 pixman_region32_t *region = calloc(1, sizeof(pixman_region32_t));
47 if (region == NULL) {
48 wl_client_post_no_memory(client);
49 return NULL;
50 }
51
52 pixman_region32_init(region);
53
54 struct wl_resource *region_resource = wl_resource_create(client,
55 &wl_region_interface, version, id);
56 if (region_resource == NULL) {
57 free(region);
58 wl_client_post_no_memory(client);
59 return NULL;
60 }
61 wl_resource_set_implementation(region_resource, ®ion_impl, region,
62 region_handle_resource_destroy);
63
64 struct wl_list *resource_link = wl_resource_get_link(region_resource);
65 if (resource_list != NULL) {
66 wl_list_insert(resource_list, resource_link);
67 } else {
68 wl_list_init(resource_link);
69 }
70
71 return region_resource;
72 }
73
wlr_region_from_resource(struct wl_resource * resource)74 pixman_region32_t *wlr_region_from_resource(struct wl_resource *resource) {
75 assert(wl_resource_instance_of(resource, &wl_region_interface,
76 ®ion_impl));
77 return wl_resource_get_user_data(resource);
78 }
79