renderer: Fix minor issue
[platform/core/uifw/libds-tizen.git] / src / indicator / indicator.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/indicator.h"
10
11 #define TIZEN_INDICATOR_VERSION 1
12
13 struct ds_tizen_indicator
14 {
15     struct wl_global *global;
16
17     struct wl_list clients;
18
19     struct wl_listener destroy;
20
21     struct {
22         struct wl_signal destroy;
23         struct wl_signal change_state;
24         struct wl_signal change_opacity_mode;
25         struct wl_signal change_visible_type;
26     } events;
27 };
28
29 struct ds_tizen_indicator_client
30 {
31     struct ds_tizen_indicator *indicator;
32
33     struct wl_resource *resource;
34     struct wl_client *wl_client;
35
36     struct wl_list infos;
37
38     struct wl_list link; // ds_tizen_indicator::clients
39 };
40
41 struct ds_tizen_indicator_info
42 {
43     struct ds_surface *surface;
44
45     enum ds_tizen_indicator_state state;
46     enum ds_tizen_indicator_opacity_mode opacity_mode;
47     enum ds_tizen_indicator_visible_type visible_type;
48
49     struct wl_list link; // ds_tizen_indicator_client::infos
50 };
51
52 static void indicator_handle_display_destroy(struct wl_listener *listener,
53         void *data);
54
55 static void indicator_bind(struct wl_client *wl_client, void *data,
56         uint32_t version, uint32_t id);
57
58 static struct ds_tizen_indicator_client *tizen_indicator_find_client(
59     struct ds_tizen_indicator *indicator,
60     struct ds_surface *surface);
61
62 static struct ds_tizen_indicator_info *tizen_indicator_find_info(
63         struct ds_tizen_indicator *indicator,
64         struct ds_surface *surface);
65
66 static struct ds_tizen_indicator_info *tizen_indicator_client_find_info(
67     struct ds_tizen_indicator_client *client,
68     struct ds_surface *surface);
69
70 static struct ds_tizen_indicator_info *tizen_indicator_client_get_info(
71         struct ds_tizen_indicator_client *client,
72         struct ds_surface *surface);
73
74 WL_EXPORT struct ds_tizen_indicator *
75 ds_tizen_indicator_create(struct wl_display *display)
76 {
77     struct ds_tizen_indicator *indicator;
78
79     indicator = calloc(1, sizeof *indicator);
80     if (!indicator) {
81         ds_err("calloc() failed.");
82         return NULL;
83     }
84
85     indicator->global = wl_global_create(display, &tizen_indicator_interface,
86             TIZEN_INDICATOR_VERSION, indicator, indicator_bind);
87     if (!indicator->global) {
88         ds_err("wl_global_create() failed. tizen_indicator_interface");
89         free(indicator);
90         return NULL;
91     }
92
93     wl_list_init(&indicator->clients);
94
95     indicator->destroy.notify = indicator_handle_display_destroy;
96     wl_display_add_destroy_listener(display, &indicator->destroy);
97
98     wl_signal_init(&indicator->events.destroy);
99     wl_signal_init(&indicator->events.change_state);
100     wl_signal_init(&indicator->events.change_opacity_mode);
101     wl_signal_init(&indicator->events.change_visible_type);
102
103         ds_inf("Global created: tizen_indicator(%p)", indicator);
104
105     return indicator;
106 }
107
108 WL_EXPORT void
109 ds_tizen_indicator_add_destroy_listener(struct ds_tizen_indicator *indicator,
110         struct wl_listener *listener)
111 {
112     wl_signal_add(&indicator->events.destroy, listener);
113 }
114
115 WL_EXPORT void
116 ds_tizen_indicator_add_change_state_listener(
117     struct ds_tizen_indicator *indicator, struct wl_listener *listener)
118 {
119     wl_signal_add(&indicator->events.change_state, listener);
120 }
121
122 WL_EXPORT void
123 ds_tizen_indicator_add_change_opacity_mode_listener(
124     struct ds_tizen_indicator *indicator, struct wl_listener *listener)
125 {
126     wl_signal_add(&indicator->events.change_opacity_mode, listener);
127 }
128
129 WL_EXPORT void
130 ds_tizen_indicator_add_change_visible_type_listener(
131     struct ds_tizen_indicator *indicator, struct wl_listener *listener)
132 {
133     wl_signal_add(&indicator->events.change_visible_type, listener);
134 }
135
136 WL_EXPORT enum ds_tizen_indicator_state
137 ds_tizen_indicator_get_state(struct ds_tizen_indicator *indicator,
138         struct ds_surface *surface)
139 {
140     struct ds_tizen_indicator_info *info;
141
142     info = tizen_indicator_find_info(indicator, surface);
143     if (info == NULL) {
144         ds_err("tizen_indicator: tizen_indicator_find_info() failed.");
145         return DS_TIZEN_INDICATOR_STATE_UNKNOWN;
146     }
147
148     return info->state;
149 }
150
151 WL_EXPORT enum ds_tizen_indicator_opacity_mode
152 ds_tizen_indicator_get_opacity_mode(struct ds_tizen_indicator *indicator,
153         struct ds_surface *surface)
154 {
155     struct ds_tizen_indicator_info *info;
156
157     info = tizen_indicator_find_info(indicator, surface);
158     if (info == NULL) {
159         ds_err("tizen_indicator: tizen_indicator_find_info() failed.");
160         return DS_TIZEN_INDICATOR_OPACITY_MODE_UNKNOWN;
161     }
162
163     return info->opacity_mode;
164 }
165
166 WL_EXPORT enum ds_tizen_indicator_visible_type
167 ds_tizen_indicator_get_visible_type(struct ds_tizen_indicator *indicator,
168         struct ds_surface *surface)
169 {
170     struct ds_tizen_indicator_info *info;
171
172     info = tizen_indicator_find_info(indicator, surface);
173     if (info == NULL) {
174         ds_err("tizen_indicator: tizen_indicator_find_info() failed.");
175         return DS_TIZEN_INDICATOR_VISIBLE_TYPE_HIDDEN;
176     }
177
178     return info->visible_type;
179 }
180
181 WL_EXPORT void
182 ds_tizen_indicator_send_flick(struct ds_tizen_indicator *indicator,
183         struct ds_surface *surface)
184 {
185     struct ds_tizen_indicator_client *client;
186
187     client = tizen_indicator_find_client(indicator, surface);
188     if (client == NULL) {
189         ds_err("tizen_indicator: tizen_indicator_find_client() failed.");
190         return;
191     }
192
193     tizen_indicator_send_flick(client->resource,
194         ds_surface_get_wl_resource(surface), 0);
195 }
196
197 static struct ds_tizen_indicator_client *
198 tizen_indicator_find_client(struct ds_tizen_indicator *indicator,
199     struct ds_surface *surface)
200 {
201     struct ds_tizen_indicator_info *info;
202     struct ds_tizen_indicator_client *client;
203
204     wl_list_for_each(client, &indicator->clients, link) {
205         info = tizen_indicator_client_find_info(client, surface);
206         if (info != NULL)
207             return client;
208     }
209
210     return NULL;
211 }
212
213 static struct ds_tizen_indicator_info *
214 tizen_indicator_find_info(struct ds_tizen_indicator *indicator,
215     struct ds_surface *surface)
216 {
217     struct ds_tizen_indicator_info *info;
218     struct ds_tizen_indicator_client *client;
219
220     wl_list_for_each(client, &indicator->clients, link) {
221         info = tizen_indicator_client_find_info(client, surface);
222         if (info != NULL)
223             return info;
224     }
225
226     return NULL;
227 }
228
229 static struct ds_tizen_indicator_info *
230 tizen_indicator_client_find_info(struct ds_tizen_indicator_client *client,
231     struct ds_surface *surface)
232 {
233     struct ds_tizen_indicator_info *info;
234
235     wl_list_for_each(info, &client->infos, link) {
236         if (surface == info->surface)
237             return info;
238     }
239
240     return NULL;
241 }
242
243 static struct ds_tizen_indicator_info *
244 tizen_indicator_client_get_info(struct ds_tizen_indicator_client *client,
245     struct ds_surface *surface)
246 {
247     struct ds_tizen_indicator_info *info;
248
249     info = tizen_indicator_client_find_info(client, surface);
250     if (info)
251         return info;
252
253     info = calloc(1, sizeof *info);
254     if (info == NULL) {
255         ds_err("calloc() failed. tizen_indicator");
256         return NULL;
257     }
258
259     info->surface = surface;
260
261     // The initial values of state, opacity_mode and visible_type are not
262     // each value of enum ds_tizen_indicator_state,
263     // enum ds_tizen_indicator_opacity_mode and
264     // enum ds_tizen_indicator_opacity_mode
265     // because of the first signal emit for change_state signal.
266     info->state = DS_TIZEN_INDICATOR_STATE_UNKNOWN;
267     info->opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_UNKNOWN;
268     info->visible_type = DS_TIZEN_INDICATOR_VISIBLE_TYPE_HIDDEN;
269
270     wl_list_insert(&client->infos, &info->link);
271
272     return info;
273 }
274
275 static void
276 indicator_handle_display_destroy(struct wl_listener *listener, void *data)
277 {
278     struct ds_tizen_indicator *indicator;
279
280     indicator = wl_container_of(listener, indicator, destroy);
281
282     ds_inf("Global destroy: indicator(%p)", indicator);
283
284     wl_signal_emit_mutable(&indicator->events.destroy, indicator);
285     wl_list_remove(&indicator->destroy.link);
286     wl_global_destroy(indicator->global);
287     free(indicator);
288 }
289
290 static void
291 indicator_handle_destroy(struct wl_client *wl_client,
292     struct wl_resource *resource)
293 {
294     struct ds_tizen_indicator_client *client;
295
296     client = wl_resource_get_user_data(resource);
297
298     if (!wl_list_empty(&client->infos)) {
299         ds_err("tizen_indicator was destroyed before children");
300         return;
301     }
302
303     wl_resource_destroy(resource);
304 }
305
306 static void
307 indicator_handle_set_state(struct wl_client *wl_client,
308     struct wl_resource *resource, struct wl_resource *surface_resource,
309     int32_t state)
310 {
311     struct ds_tizen_indicator_client *client;
312     struct ds_tizen_indicator_info *info;
313     struct ds_surface *surface;
314     enum ds_tizen_indicator_state indicator_state;
315
316     ds_inf("tizen_indicator: set_state : state %d", state);
317
318     client = wl_resource_get_user_data(resource);
319     surface = ds_surface_from_resource(surface_resource);
320
321     info = tizen_indicator_client_get_info(client, surface);
322     if (info == NULL) {
323         ds_err("tizen_indicator_client_get_info() failed. tizen_indicator");
324         wl_client_post_no_memory(wl_client);
325         return;
326     }
327
328     switch (state) {
329         case TIZEN_INDICATOR_STATE_OFF:
330             indicator_state = DS_TIZEN_INDICATOR_STATE_OFF;
331             break;
332         case TIZEN_INDICATOR_STATE_ON:
333             indicator_state = DS_TIZEN_INDICATOR_STATE_ON;
334             break;
335         default:
336             indicator_state = DS_TIZEN_INDICATOR_STATE_UNKNOWN;
337             break;
338     }
339
340     if (info->state != indicator_state) {
341         ds_inf("tizen_indicator: surface : %p, change_state : %d -> %d",
342             surface, info->state, indicator_state);
343         info->state = indicator_state;
344
345         wl_signal_emit_mutable(&client->indicator->events.change_state, surface);
346     }
347 }
348
349 static void
350 indicator_handle_set_opacity_mode(struct wl_client *wl_client,
351     struct wl_resource *resource, struct wl_resource *surface_resource,
352     int32_t mode)
353 {
354     struct ds_tizen_indicator_client *client;
355     struct ds_tizen_indicator_info *info;
356     struct ds_surface *surface;
357     enum ds_tizen_indicator_opacity_mode opacity_mode;
358
359     ds_inf("tizen_indicator: set_opacity_mode : opacity_mode %d", mode);
360
361     client = wl_resource_get_user_data(resource);
362     surface = ds_surface_from_resource(surface_resource);
363
364     info = tizen_indicator_client_get_info(client, surface);
365     if (info == NULL) {
366         ds_err("tizen_indicator_client_get_info() failed. tizen_indicator");
367         wl_client_post_no_memory(wl_client);
368         return;
369     }
370
371     switch (mode) {
372         case TIZEN_INDICATOR_OPACITY_MODE_OPAQUE:
373             opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_OPAQUE;
374             break;
375         case TIZEN_INDICATOR_OPACITY_MODE_TRANSLUCENT:
376             opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSLUCENT;
377             break;
378         case TIZEN_INDICATOR_OPACITY_MODE_TRANSPARENT:
379             opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_TRANSPARENT;
380             break;
381         case TIZEN_INDICATOR_OPACITY_MODE_BG_TRANSPARENT:
382             opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_BG_TRANSPARENT;
383             break;
384         default:
385             opacity_mode = DS_TIZEN_INDICATOR_OPACITY_MODE_UNKNOWN;
386             break;
387     }
388
389     if (info->opacity_mode != opacity_mode) {
390         ds_inf("tizen_indicator: surface : %p, change_opacity_mode : %d -> %d",
391             surface, info->opacity_mode, opacity_mode);
392         info->opacity_mode = opacity_mode;
393
394         wl_signal_emit_mutable(&client->indicator->events.change_opacity_mode, surface);
395     }
396 }
397
398 static void
399 indicator_handle_set_visible_type(struct wl_client *wl_client,
400     struct wl_resource *resource, struct wl_resource *surface_resource,
401     int32_t type)
402 {
403     struct ds_tizen_indicator_client *client;
404     struct ds_tizen_indicator_info *info;
405     struct ds_surface *surface;
406     enum ds_tizen_indicator_visible_type visible_type;
407
408     ds_inf("tizen_indicator: set_visible_type : visible_type %d", type);
409
410     client = wl_resource_get_user_data(resource);
411     surface = ds_surface_from_resource(surface_resource);
412
413     info = tizen_indicator_client_get_info(client, surface);
414     if (info == NULL) {
415         ds_err("tizen_indicator_client_get_info() failed. tizen_indicator");
416         wl_client_post_no_memory(wl_client);
417         return;
418     }
419
420     switch (type) {
421         case TIZEN_INDICATOR_VISIBLE_TYPE_SHOWN:
422             visible_type = DS_TIZEN_INDICATOR_VISIBLE_TYPE_SHOWN;
423             break;
424         default:
425             visible_type = DS_TIZEN_INDICATOR_VISIBLE_TYPE_HIDDEN;
426             break;
427     }
428
429     if (info->visible_type != visible_type) {
430         ds_inf("tizen_indicator: surface : %p, change_visible_type : %d -> %d",
431             surface, info->visible_type, visible_type);
432         info->visible_type = visible_type;
433
434         wl_signal_emit_mutable(&client->indicator->events.change_visible_type, surface);
435     }
436 }
437
438 static const struct tizen_indicator_interface indicator_impl =
439 {
440    indicator_handle_destroy,
441    indicator_handle_set_state,
442    indicator_handle_set_opacity_mode,
443    indicator_handle_set_visible_type,
444 };
445
446 static void
447 _tizen_indicator_client_handle_destroy(struct wl_resource *resource)
448 {
449     struct ds_tizen_indicator_client *client;
450     struct ds_tizen_indicator_info *info, *tmp;
451
452     client = wl_resource_get_user_data(resource);
453
454     ds_inf("_tizen_indicator_client_handle_destroy (client:%p)", client);
455
456     wl_list_for_each_safe(info, tmp, &client->infos, link) {
457         wl_list_remove(&info->link);
458         free(info);
459     }
460
461     wl_list_remove(&client->link);
462     free(client);
463 }
464
465 static void
466 indicator_bind(struct wl_client *wl_client, void *data, uint32_t version,
467         uint32_t id)
468 {
469     struct ds_tizen_indicator *indicator = data;
470     struct ds_tizen_indicator_client *client;
471
472     client = calloc(1, sizeof *client);
473     if (client == NULL) {
474         ds_err("calloc() failed. tizen_indicator");
475         wl_client_post_no_memory(wl_client);
476         return;
477     }
478
479     ds_inf("tizen_indicator_client binds. (client:%p)", client);
480
481     client->indicator = indicator;
482     client->wl_client = wl_client;
483
484     wl_list_init(&client->infos);
485
486     client->resource = wl_resource_create(wl_client, &tizen_indicator_interface,
487             MIN(version, TIZEN_INDICATOR_VERSION), id);
488     if (client->resource == NULL) {
489         ds_err("tizen_indicator : wl_resource_create() failed.");
490         free(client);
491         wl_client_post_no_memory(wl_client);
492         return;
493     }
494
495     wl_resource_set_implementation(client->resource, &indicator_impl, client,
496             _tizen_indicator_client_handle_destroy);
497
498     wl_list_insert(&indicator->clients, &client->link);
499 }