renderer: Fix minor issue
[platform/core/uifw/libds-tizen.git] / src / global_resource / global_resource.c
1 #include <assert.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <wayland-server.h>
5 #include <tizen-extension-server-protocol.h>
6 #include <libds/log.h>
7
8 #include "util.h"
9 #include "libds-tizen/global_resource.h"
10
11 #define TIZEN_SURFACE_VERSION 1
12
13 static uint32_t unique_id = 0;
14
15 struct ds_tizen_global_resource
16 {
17     struct wl_global *global;
18
19     struct wl_list clients;
20
21     struct wl_listener destroy;
22
23     struct {
24         struct wl_signal destroy;
25         struct wl_signal get_resource_info;
26     } events;
27 };
28
29 struct ds_tizen_global_resource_client
30 {
31     struct ds_tizen_global_resource *global_resource;
32
33     struct wl_resource *resource;
34     struct wl_client *wl_client;
35
36     struct wl_list infos;
37
38     struct {
39         struct wl_signal destroy;
40     } events;
41
42     struct wl_list link; // ds_tizen_global_resource::clients
43 };
44
45 struct ds_tizen_global_resource_info
46 {
47     struct ds_tizen_global_resource_client *client;
48
49     struct wl_resource *resource;
50
51     struct ds_surface *surface;
52
53     uint32_t universal_id;
54
55     struct wl_list link; // ds_tizen_global_resource_client::infos
56 };
57
58 static void resource_handle_display_destroy(struct wl_listener *listener,
59         void *data);
60
61 static void resource_bind(struct wl_client *wl_client, void *data,
62         uint32_t version, uint32_t id);
63
64 static struct ds_tizen_global_resource_info *tizen_global_resource_client_find_info(
65     struct ds_tizen_global_resource_client *client,
66     struct ds_surface *surface);
67
68 static struct ds_tizen_global_resource_info *tizen_global_resource_client_get_info(
69         struct ds_tizen_global_resource_client *client,
70         struct ds_surface *surface);
71
72 WL_EXPORT struct ds_tizen_global_resource *
73 ds_tizen_global_resource_create(struct wl_display *display)
74 {
75     struct ds_tizen_global_resource *global_resource;
76
77     global_resource = calloc(1, sizeof *global_resource);
78     if (!global_resource) {
79         ds_err("calloc() failed.");
80         return NULL;
81     }
82
83     global_resource->global = wl_global_create(display, &tizen_surface_interface,
84             TIZEN_SURFACE_VERSION, global_resource, resource_bind);
85     if (!global_resource->global) {
86         ds_err("wl_global_create() failed. tizen_resource_interface");
87         free(global_resource);
88         return NULL;
89     }
90
91     wl_list_init(&global_resource->clients);
92
93     global_resource->destroy.notify = resource_handle_display_destroy;
94     wl_display_add_destroy_listener(display, &global_resource->destroy);
95
96     wl_signal_init(&global_resource->events.destroy);
97     wl_signal_init(&global_resource->events.get_resource_info);
98
99     ds_inf("Global created: tizen_global_resource(%p)", global_resource);
100
101     return global_resource;
102 }
103
104 WL_EXPORT void
105 ds_tizen_global_resource_add_destroy_listener(
106         struct ds_tizen_global_resource *global_resource,
107         struct wl_listener *listener)
108 {
109     wl_signal_add(&global_resource->events.destroy, listener);
110 }
111
112 WL_EXPORT void
113 ds_tizen_global_resource_add_get_resource_info_listener(
114         struct ds_tizen_global_resource *global_resource,
115         struct wl_listener *listener)
116 {
117     wl_signal_add(&global_resource->events.get_resource_info, listener);
118 }
119
120 WL_EXPORT void
121 ds_tizen_global_resource_info_add_destroy_listener(
122         struct ds_tizen_global_resource_info *info,
123         struct wl_listener *listener)
124 {
125     wl_signal_add(&info->client->events.destroy, listener);
126 }
127
128 WL_EXPORT struct ds_surface *
129 ds_tizen_global_resource_info_get_surface(
130     struct ds_tizen_global_resource_info *info)
131 {
132     return info->surface;
133 }
134
135 WL_EXPORT uint32_t
136 ds_tizen_global_resource_get_universal_id(
137     struct ds_tizen_global_resource_info *info)
138 {
139     return info->universal_id;
140 }
141
142 static struct ds_tizen_global_resource_info *
143 tizen_global_resource_client_find_info(
144     struct ds_tizen_global_resource_client *client,
145     struct ds_surface *surface)
146 {
147     struct ds_tizen_global_resource_info *info;
148
149     wl_list_for_each(info, &client->infos, link) {
150         if (surface == info->surface)
151             return info;
152     }
153
154     return NULL;
155 }
156
157 static struct ds_tizen_global_resource_info *
158 tizen_global_resource_client_get_info(
159     struct ds_tizen_global_resource_client *client,
160     struct ds_surface *surface)
161 {
162     struct ds_tizen_global_resource_info *info;
163
164     info = tizen_global_resource_client_find_info(client, surface);
165     if (info)
166         return info;
167
168     info = calloc(1, sizeof *info);
169     if (info == NULL) {
170         ds_err("calloc() failed. tizen_global_resource");
171         return NULL;
172     }
173
174     info->client = client;
175     info->surface = surface;
176
177     wl_list_insert(&client->infos, &info->link);
178
179     return info;
180 }
181
182 static void
183 resource_handle_display_destroy(struct wl_listener *listener, void *data)
184 {
185     struct ds_tizen_global_resource *global_resource;
186
187     global_resource = wl_container_of(listener, global_resource, destroy);
188
189     ds_inf("Global destroy: resource(%p)", global_resource);
190
191     wl_signal_emit(&global_resource->events.destroy, global_resource);
192     wl_list_remove(&global_resource->destroy.link);
193     wl_global_destroy(global_resource->global);
194     free(global_resource);
195 }
196
197 static void
198 resource_handle_destroy(struct wl_client *wl_client,
199     struct wl_resource *resource)
200 {
201     wl_resource_destroy(resource);
202 }
203
204 static const struct tizen_resource_interface resource_impl =
205 {
206    resource_handle_destroy,
207 };
208
209 static void
210 _tizen_surface_handle_destroy(struct wl_resource *resource)
211 {
212     struct ds_tizen_global_resource_info *info;
213
214     info = wl_resource_get_user_data(resource);
215
216     ds_inf("_tizen_surface_handle_destroy (info:%p)", info);
217
218     wl_signal_emit(&info->client->events.destroy, info);
219     wl_list_remove(&info->link);
220     free(info);
221 }
222
223 static void
224 surface_handle_get_tizen_global_resource(struct wl_client *wl_client,
225     struct wl_resource *resource,uint32_t id,
226     struct wl_resource *surface_resource)
227 {
228     struct ds_tizen_global_resource_client *client;
229     struct ds_tizen_global_resource_info *info;
230     struct ds_surface *surface;
231
232     ds_inf("tizen_global_resource: surface_handle_get_tizen_global_resource");
233
234     client = wl_resource_get_user_data(resource);
235     surface = ds_surface_from_resource(surface_resource);
236
237     info = tizen_global_resource_client_get_info(client, surface);
238     if (info == NULL) {
239         ds_err("tizen_global_resource_client_get_info() failed.");
240         wl_client_post_no_memory(wl_client);
241         return;
242     }
243
244     info->resource = wl_resource_create(wl_client,
245         &tizen_resource_interface, wl_resource_get_version(resource),
246         id);
247     if (info->resource == NULL) {
248         ds_err("tizen_global_resource : wl_resource_create() failed.");
249         wl_list_remove(&info->link);
250         free(info);
251         wl_client_post_no_memory(wl_client);
252         return;
253     }
254
255     // generate the univeral_id;
256     info->universal_id = unique_id++;
257
258     wl_resource_set_implementation(info->resource, &resource_impl, info,
259         _tizen_surface_handle_destroy);
260
261     wl_signal_emit(&client->global_resource->events.get_resource_info, info);
262
263     tizen_resource_send_resource_id(info->resource, info->universal_id);
264 }
265
266 static void
267 surface_handle_destroy(struct wl_client *wl_client,
268     struct wl_resource *resource)
269 {
270     struct ds_tizen_global_resource_client *client;
271
272     client = wl_resource_get_user_data(resource);
273
274     if (!wl_list_empty(&client->infos)) {
275         ds_err("tizen_global_resource was destroyed before children");
276         return;
277     }
278
279     wl_resource_destroy(resource);
280 }
281
282 static const struct tizen_surface_interface surface_impl =
283 {
284    surface_handle_get_tizen_global_resource,
285    surface_handle_destroy,
286 };
287
288 static void
289 _tizen_global_resource_client_handle_destroy(struct wl_resource *resource)
290 {
291     struct ds_tizen_global_resource_client *client;
292     struct ds_tizen_global_resource_info *info, *tmp;
293
294     client = wl_resource_get_user_data(resource);
295
296     ds_inf("_tizen_global_resource_client_handle_destroy (client:%p)", client);
297
298     wl_list_for_each_safe(info, tmp, &client->infos, link) {
299         wl_signal_emit(&info->client->events.destroy, info);
300         wl_list_remove(&info->link);
301         free(info);
302     }
303
304     wl_list_remove(&client->link);
305     free(client);
306 }
307
308 static void
309 resource_bind(struct wl_client *wl_client, void *data, uint32_t version,
310         uint32_t id)
311 {
312     struct ds_tizen_global_resource *global_resource = data;
313     struct ds_tizen_global_resource_client *client;
314
315     client = calloc(1, sizeof *client);
316     if (client == NULL) {
317         ds_err("calloc() failed. tizen_global_resource");
318         wl_client_post_no_memory(wl_client);
319         return;
320     }
321
322     ds_inf("tizen_global_resource_client binds. (client:%p)", client);
323
324     client->global_resource = global_resource;
325     client->wl_client = wl_client;
326
327     wl_list_init(&client->infos);
328
329     client->resource = wl_resource_create(wl_client, &tizen_surface_interface,
330             MIN(version, TIZEN_SURFACE_VERSION), id);
331
332     if (client->resource == NULL) {
333         ds_err("tizen_global_resource : wl_resource_create() failed.");
334         free(client);
335         wl_client_post_no_memory(wl_client);
336         return;
337     }
338
339     wl_resource_set_implementation(client->resource, &surface_impl, client,
340             _tizen_global_resource_client_handle_destroy);
341
342     wl_signal_init(&client->events.destroy);
343
344     wl_list_insert(&global_resource->clients, &client->link);
345 }