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, &region_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 		&region_impl));
77 	return wl_resource_get_user_data(resource);
78 }
79