shell : add null check of pepper list when using pepper_list_for_each_list
[platform/core/uifw/headless-server.git] / src / shell / shell.c
1 /*
2 * Copyright © 2019 Samsung Electronics co., Ltd. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 #include <pepper.h>
30 #include <pepper-output-backend.h>
31 #include <xdg-shell-unstable-v6-server-protocol.h>
32 #include <tizen-extension-server-protocol.h>
33
34 #include "headless_server.h"
35
36 #define UPDATE_SURFACE_TYPE     0               //update the surface_type(map. unmap)
37 #define SET_UPDATE(x, type)     (x |= ((uint32_t)(1<<type)))
38 #define IS_UPDATE(x, type)      (!!(x & ((uint32_t)(1<<type))))
39
40 typedef enum {
41         HEADLESS_SURFACE_NONE,
42         HEADLESS_SURFACE_TOPLEVEL,
43         HEADLESS_SURFACE_POPUP
44 } headless_surface_type_t;
45
46 typedef struct HEADLESS_SHELL headless_shell_t;
47 typedef struct HEADLESS_SHELL_SURFACE headless_shell_surface_t;
48
49 struct HEADLESS_SHELL{
50         pepper_compositor_t *compositor;
51         struct wl_global *zxdg_shell;
52         struct wl_global *tizen_policy;
53         struct wl_event_source *cb_idle;
54
55         pepper_view_t *focus;
56         pepper_view_t *top_mapped;
57         pepper_view_t *top_visible;
58
59         pepper_event_listener_t *surface_add_listener;
60         pepper_event_listener_t *surface_remove_listener;
61         pepper_event_listener_t *view_remove_listener;
62 };
63
64 struct HEADLESS_SHELL_SURFACE{
65         headless_shell_t *hs_shell;
66         pepper_surface_t *surface;
67         pepper_view_t *view;
68         uint32_t        updates;
69         uint8_t         visibility;
70
71         headless_surface_type_t surface_type;
72         struct wl_resource *zxdg_shell_surface;
73         struct wl_resource *zxdg_surface;       /*resource of toplevel, popup and etc*/
74         struct wl_resource *tizen_visibility;
75         uint32_t last_ack_configure;
76
77         pepper_bool_t skip_focus;
78
79         pepper_event_listener_t *cb_commit;
80 };
81
82 static void
83 headless_shell_cb_surface_commit(pepper_event_listener_t *listener,
84                                                                                 pepper_object_t *object,
85                                                                                 uint32_t id, void *info, void *data);
86 static void
87 headless_shell_add_idle(headless_shell_t *shell);
88
89
90 static void
91 headless_shell_send_visiblity(pepper_view_t *view, uint8_t visibility);
92
93 const static int KEY_SHELL = 0;
94
95 static void
96 zxdg_toplevel_cb_resource_destroy(struct wl_resource *resource)
97 {
98         headless_shell_surface_t *hs_surface = (headless_shell_surface_t *)wl_resource_get_user_data(resource);
99
100         PEPPER_CHECK(hs_surface, return, "fail to get headless_surface.\n");
101         PEPPER_CHECK((hs_surface->surface_type == HEADLESS_SURFACE_TOPLEVEL), return, "Invalid surface type.\n");
102         PEPPER_CHECK((hs_surface->zxdg_surface == resource), return, "Invalid surface.");
103
104         PEPPER_TRACE("[SHELL] zxdg_toplevel_cb_resource_destroy: view:%p, hs_surface:%p\n", hs_surface->view, hs_surface);
105
106         if (hs_surface->view) {
107                 pepper_view_unmap(hs_surface->view);
108                 headless_shell_add_idle(hs_surface->hs_shell);
109         }
110
111         hs_surface->surface_type = HEADLESS_SURFACE_NONE;
112         hs_surface->zxdg_surface = NULL;
113         SET_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE);
114 }
115
116 static void
117 zxdg_toplevel_cb_destroy(struct wl_client *client, struct wl_resource *resource)
118 {
119         wl_resource_destroy(resource);
120 }
121
122 static void
123 zxdg_toplevel_cb_parent_set(struct wl_client *client,
124                             struct wl_resource *resource,
125                             struct wl_resource *res_parent)
126 {
127 }
128
129 static void
130 zxdg_toplevel_cb_title_set(struct wl_client *client,
131                            struct wl_resource *resource,
132                            const char *title)
133 {
134 }
135
136 static void
137 zxdg_toplevel_cb_app_id_set(struct wl_client *client,
138                             struct wl_resource *resource,
139                             const char *app_id)
140 {
141 }
142
143 static void
144 zxdg_toplevel_cb_win_menu_show(struct wl_client *client,
145                                struct wl_resource *resource,
146                                struct wl_resource *res_seat,
147                                uint32_t serial,
148                                int32_t x,
149                                int32_t y)
150 {
151 }
152
153 static void
154 zxdg_toplevel_cb_move(struct wl_client *client,
155                       struct wl_resource *resource,
156                       struct wl_resource *res_seat,
157                       uint32_t serial)
158 {
159 }
160
161 static void
162 zxdg_toplevel_cb_resize(struct wl_client *client,
163                         struct wl_resource *resource,
164                         struct wl_resource *res_seat,
165                         uint32_t serial,
166                         uint32_t edges)
167 {
168 }
169
170 static void
171 zxdg_toplevel_cb_max_size_set(struct wl_client *client,
172                               struct wl_resource *resource,
173                               int32_t w,
174                               int32_t h)
175 {
176 }
177
178 static void
179 zxdg_toplevel_cb_min_size_set(struct wl_client *client,
180                               struct wl_resource *resource,
181                               int32_t w,
182                               int32_t h)
183 {
184 }
185
186 static void
187 zxdg_toplevel_cb_maximized_set(struct wl_client *client, struct wl_resource *resource)
188 {
189 }
190
191 static void
192 zxdg_toplevel_cb_maximized_unset(struct wl_client *client, struct wl_resource *resource)
193 {
194 }
195
196 static void
197 zxdg_toplevel_cb_fullscreen_set(struct wl_client *client,
198                                 struct wl_resource *resource,
199                                 struct wl_resource *res_output)
200 {
201 }
202
203 static void
204 zxdg_toplevel_cb_fullscreen_unset(struct wl_client *client, struct wl_resource *resource)
205 {
206 }
207
208 static void
209 zxdg_toplevel_cb_minimized_set(struct wl_client *client, struct wl_resource *resource)
210 {
211 }
212
213 static const struct zxdg_toplevel_v6_interface zxdg_toplevel_interface =
214 {
215         zxdg_toplevel_cb_destroy,
216         zxdg_toplevel_cb_parent_set,
217         zxdg_toplevel_cb_title_set,
218         zxdg_toplevel_cb_app_id_set,
219         zxdg_toplevel_cb_win_menu_show,
220         zxdg_toplevel_cb_move,
221         zxdg_toplevel_cb_resize,
222         zxdg_toplevel_cb_max_size_set,
223         zxdg_toplevel_cb_min_size_set,
224         zxdg_toplevel_cb_maximized_set,
225         zxdg_toplevel_cb_maximized_unset,
226         zxdg_toplevel_cb_fullscreen_set,
227         zxdg_toplevel_cb_fullscreen_unset,
228         zxdg_toplevel_cb_minimized_set
229 };
230
231 static void
232 zxdg_popup_cb_resource_destroy(struct wl_resource *resource)
233 {
234         headless_shell_surface_t *hs_surface = (headless_shell_surface_t *)wl_resource_get_user_data(resource);
235
236         PEPPER_CHECK(hs_surface, return, "fail to get headless_surface.\n");
237         PEPPER_CHECK((hs_surface->surface_type == HEADLESS_SURFACE_POPUP), return, "Invalid surface type.\n");
238         PEPPER_CHECK((hs_surface->zxdg_surface == resource), return, "Invalid surface.");
239
240         hs_surface->surface_type = HEADLESS_SURFACE_NONE;
241         hs_surface->zxdg_surface = NULL;
242         SET_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE);
243 }
244
245 static void
246 zxdg_popup_cb_destroy(struct wl_client *client, struct wl_resource *resource)
247 {
248         wl_resource_destroy(resource);
249 }
250
251 static void
252 zxdg_popup_cb_grab(struct wl_client *client,
253                    struct wl_resource *resource,
254                    struct wl_resource *res_seat,
255                    uint32_t serial)
256 {
257 }
258
259 static const struct zxdg_popup_v6_interface zxdg_popup_interface =
260 {
261         zxdg_popup_cb_destroy,
262         zxdg_popup_cb_grab
263 };
264
265 static void
266 zxdg_surface_cb_resource_destroy(struct wl_resource *resource)
267 {
268         headless_shell_surface_t *hs_surface;
269
270         hs_surface = wl_resource_get_user_data(resource);
271         PEPPER_CHECK(hs_surface, return, "fail to get hs_surface\n");
272
273         PEPPER_TRACE("[SHELL] zxdg_surface_cb_resource_destroy: hs_surface:%p view:%p\n", hs_surface, hs_surface->view);
274
275         if (hs_surface->view) {
276                 pepper_view_destroy(hs_surface->view);
277                 hs_surface->view = NULL;
278         }
279
280         if (hs_surface->cb_commit) {
281                 pepper_event_listener_remove(hs_surface->cb_commit);
282                 hs_surface->cb_commit = NULL;
283         }
284
285         hs_surface->zxdg_shell_surface = NULL;
286         hs_surface->skip_focus = PEPPER_FALSE;
287         hs_surface->visibility = TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED;
288
289         SET_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE);
290         headless_shell_add_idle(hs_surface->hs_shell);
291 }
292
293 static void
294 zxdg_surface_cb_destroy(struct wl_client *client, struct wl_resource *resource)
295 {
296         wl_resource_destroy(resource);
297 }
298
299 static void
300 zxdg_surface_cb_toplevel_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
301 {
302         headless_shell_surface_t *hs_surface = (headless_shell_surface_t *)wl_resource_get_user_data(resource);
303         struct wl_resource *new_res;
304
305         PEPPER_CHECK(hs_surface, return, "fail to get headless_surface\n");
306         PEPPER_CHECK((hs_surface->zxdg_surface == NULL), return, "alwreay assign zdg_surface:%p role:%d\n", hs_surface->zxdg_surface, hs_surface->surface_type);
307
308         new_res = wl_resource_create(client, &zxdg_toplevel_v6_interface, 1, id);
309         if (!new_res) {
310                 PEPPER_ERROR("fail to create zxdg_toplevel");
311                 wl_resource_post_no_memory(resource);
312                 return;
313         }
314
315         wl_resource_set_implementation(new_res,
316                         &zxdg_toplevel_interface,
317                         hs_surface,
318                         zxdg_toplevel_cb_resource_destroy);
319
320         hs_surface->surface_type = HEADLESS_SURFACE_TOPLEVEL;
321         hs_surface->zxdg_surface = new_res;
322
323         SET_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE);
324 }
325
326 static void
327 zxdg_surface_cb_popup_get(struct wl_client *client,
328                                                                         struct wl_resource *resource,
329                                                                         uint32_t id,
330                                                                         struct wl_resource *res_parent,
331                                                                         struct wl_resource *res_pos)
332 {
333         headless_shell_surface_t *hs_surface = (headless_shell_surface_t *)wl_resource_get_user_data(resource);
334         struct wl_resource *new_res;
335
336         PEPPER_CHECK(hs_surface, return, "fail to get headless_surface\n");
337         PEPPER_CHECK((hs_surface->zxdg_surface == NULL), return, "alwreay assign zdg_surface:%p role:%d\n", hs_surface->zxdg_surface, hs_surface->surface_type);
338
339         new_res = wl_resource_create(client, &zxdg_popup_v6_interface, 1, id);
340         if (!new_res) {
341                 PEPPER_ERROR("fail to create popup");
342                 wl_resource_post_no_memory(resource);
343                 return;
344         }
345
346         wl_resource_set_implementation(new_res,
347                                   &zxdg_popup_interface,
348                                   hs_surface,
349                                   zxdg_popup_cb_resource_destroy);
350
351         hs_surface->surface_type = HEADLESS_SURFACE_POPUP;
352         hs_surface->zxdg_surface = new_res;
353
354         SET_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE);
355 }
356
357 static void
358 zxdg_surface_cb_win_geometry_set(struct wl_client *client,
359                                    struct wl_resource *resource,
360                                    int32_t x,
361                                    int32_t y,
362                                    int32_t w,
363                                    int32_t h)
364 {
365 }
366
367 static void
368 zxdg_surface_cb_configure_ack(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
369 {
370         headless_shell_surface_t *hs_surface;
371
372         hs_surface = wl_resource_get_user_data(resource);
373         PEPPER_CHECK(hs_surface, return, "fail to get headless_shell_surface\n");
374
375         hs_surface->last_ack_configure = serial;
376 }
377
378 static const struct zxdg_surface_v6_interface zxdg_surface_interface =
379 {
380         zxdg_surface_cb_destroy,
381         zxdg_surface_cb_toplevel_get,
382         zxdg_surface_cb_popup_get,
383         zxdg_surface_cb_win_geometry_set,
384         zxdg_surface_cb_configure_ack
385 };
386
387 static void
388 zxdg_positioner_cb_destroy(struct wl_client *client, struct wl_resource *resource)
389 {
390         wl_resource_destroy(resource);
391 }
392
393 static void
394 zxdg_positioner_cb_size_set(struct wl_client *client,
395                             struct wl_resource *resource,
396                             int32_t w, int32_t h)
397 {
398 }
399
400 static void
401 zxdg_positioner_cb_anchor_rect_set(struct wl_client *client,
402                                    struct wl_resource *resource,
403                                    int32_t x, int32_t y, int32_t w, int32_t h)
404 {
405 }
406
407 static void
408 zxdg_positioner_cb_anchor_set(struct wl_client *client,
409                               struct wl_resource *resource,
410                               enum zxdg_positioner_v6_anchor anchor)
411 {
412 }
413
414 static void
415 zxdg_positioner_cb_gravity_set(struct wl_client *client,
416                                struct wl_resource *resource,
417                                enum zxdg_positioner_v6_gravity gravity)
418 {
419 }
420
421 static void
422 zxdg_positioner_cb_constraint_adjustment_set(struct wl_client *client,
423                                              struct wl_resource *resource,
424                                              enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment)
425 {
426 }
427
428 static void
429 zxdg_positioner_cb_offset_set(struct wl_client *client,
430                               struct wl_resource *resource,
431                               int32_t x, int32_t y)
432 {
433 }
434
435 static const struct zxdg_positioner_v6_interface zxdg_positioner_interface =
436 {
437         zxdg_positioner_cb_destroy,
438         zxdg_positioner_cb_size_set,
439         zxdg_positioner_cb_anchor_rect_set,
440         zxdg_positioner_cb_anchor_set,
441         zxdg_positioner_cb_gravity_set,
442         zxdg_positioner_cb_constraint_adjustment_set,
443         zxdg_positioner_cb_offset_set,
444 };
445
446 static void
447 zxdg_shell_cb_destroy(struct wl_client *client, struct wl_resource *resource)
448 {
449         PEPPER_TRACE("Destroy zxdg_shell\n");
450
451         wl_resource_destroy(resource);
452 }
453
454 static void
455 zxdg_shell_cb_positioner_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
456 {
457         struct wl_resource *new_res;
458
459         PEPPER_TRACE("Create zxdg_positoiner\n");
460
461         new_res = wl_resource_create(client, &zxdg_positioner_v6_interface, 1, id);
462         if (!new_res)
463         {
464                 PEPPER_ERROR("fail to create zxdg_positioner\n");
465                 wl_resource_post_no_memory(resource);
466                 return;
467         }
468
469         wl_resource_set_implementation(new_res, &zxdg_positioner_interface, NULL, NULL);
470 }
471
472 static void
473 zxdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *wsurface)
474 {
475         headless_shell_t *hs;
476         headless_shell_surface_t *hs_surface = NULL;
477         pepper_surface_t *psurface;
478         const char *role;
479
480         hs = wl_resource_get_user_data(resource);
481         if (!hs) {
482                 PEPPER_ERROR("fail to get headless_shell\n");
483                 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
484                                 "failed to get headless shell");
485                 return;
486         }
487
488         psurface = wl_resource_get_user_data(wsurface);
489         PEPPER_CHECK(psurface, goto error, "faile to get pepper_surface\n");
490
491         hs_surface = (headless_shell_surface_t *)pepper_object_get_user_data((pepper_object_t *)psurface, wsurface);
492         if (!hs_surface) {
493                 PEPPER_ERROR("fail to get headless_shell_surface_t: %p key:%p\n", psurface, wsurface);
494                 wl_resource_post_no_memory(resource);
495                 return;
496         }
497
498         hs_surface->zxdg_shell_surface = wl_resource_create(client, &zxdg_surface_v6_interface, 1, id);
499         if (!hs_surface->zxdg_shell_surface) {
500                 PEPPER_ERROR("fail to create the zxdg_surface\n");
501                 wl_resource_post_no_memory(resource);
502                 goto error;
503         }
504
505         wl_resource_set_implementation(hs_surface->zxdg_shell_surface,
506                         &zxdg_surface_interface,
507                         hs_surface,
508                         zxdg_surface_cb_resource_destroy);
509
510         hs_surface->view = pepper_compositor_add_view(hs->compositor);
511         if (!hs_surface->view) {
512                 PEPPER_ERROR("fail to create the pepper_view\n");
513                 wl_resource_post_no_memory(resource);
514                 goto error;
515         }
516
517         if (!pepper_view_set_surface(hs_surface->view, psurface)) {
518                 PEPPER_ERROR("fail to set surface\n");
519                 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
520                                 "Assign set psurface to pview");
521                 goto error;
522         }
523
524         hs_surface->cb_commit = pepper_object_add_event_listener((pepper_object_t *)psurface,
525                                                                                                                         PEPPER_EVENT_SURFACE_COMMIT, 0, headless_shell_cb_surface_commit, hs_surface);
526
527         role = pepper_surface_get_role(psurface);
528         if (!role) {
529                 if (!pepper_surface_set_role(psurface, "xdg_surface")) {
530                         PEPPER_ERROR("fail to set role\n");
531                         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
532                                         "Assign \"xdg_surface\" to wl_surface failed\n");
533                         goto error;
534                 }
535         } else {
536                 PEPPER_CHECK(!strcmp(role, "xdg_surface"), goto error, "surface has alweady role %s\n", role);
537         }
538
539         PEPPER_TRACE("[SHELL] create zxdg_surface:%p, pview:%p, psurface:%p\n",
540                         hs_surface->zxdg_shell_surface,
541                         hs_surface->view,
542                         psurface);
543
544         return;
545 error:
546         if (hs_surface) {
547                 if (hs_surface->view) {
548                         pepper_view_destroy(hs_surface->view);
549                         hs_surface->view = NULL;
550                 }
551
552                 if (hs_surface->zxdg_shell_surface) {
553                         wl_resource_destroy(hs_surface->zxdg_shell_surface);
554                         hs_surface->zxdg_shell_surface = NULL;
555                 }
556         }
557 }
558
559 static void
560 zxdg_shell_cb_pong(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
561 {
562
563 }
564
565 static const struct zxdg_shell_v6_interface zxdg_shell_interface =
566 {
567         zxdg_shell_cb_destroy,
568         zxdg_shell_cb_positioner_create,
569         zxdg_shell_cb_surface_get,
570         zxdg_shell_cb_pong
571 };
572
573 static void
574 zxdg_shell_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
575 {
576         struct wl_resource *resource;
577         headless_shell_t *hs = (headless_shell_t *)data;
578
579         PEPPER_TRACE("Bind zxdg_shell\n");
580
581         /* Create resource for zxdg_shell_v6 */
582         resource = wl_resource_create(client,
583                         &zxdg_shell_v6_interface,
584                         version,
585                         id);
586         PEPPER_CHECK(resource, goto err_shell, "fail to create the zxdg_shell_v6\n");
587
588         wl_resource_set_implementation(resource, &zxdg_shell_interface, hs, NULL);
589
590         return;
591 err_shell:
592         wl_client_post_no_memory(client);
593 }
594
595 static pepper_bool_t
596 zxdg_init(headless_shell_t *shell)
597 {
598         struct wl_display *display;
599
600         display = pepper_compositor_get_display(shell->compositor);
601
602         shell->zxdg_shell = wl_global_create(display, &zxdg_shell_v6_interface, 1, shell, zxdg_shell_cb_bind);
603         PEPPER_CHECK(shell->zxdg_shell, return PEPPER_FALSE, "fail to create zxdg_shell\n");
604
605         return PEPPER_TRUE;
606 }
607
608 void
609 zxdg_deinit(headless_shell_t *shell)
610 {
611         if (shell->zxdg_shell)
612                 wl_global_destroy(shell->zxdg_shell);
613 }
614
615 static void
616 tizen_visibility_cb_destroy(struct wl_client *client, struct wl_resource *res_tzvis)
617 {
618         wl_resource_destroy(res_tzvis);
619 }
620
621 static const struct tizen_visibility_interface tizen_visibility =
622 {
623         tizen_visibility_cb_destroy
624 };
625
626 static void
627 tizen_visibility_cb_vis_destroy(struct wl_resource *res_tzvis)
628 {
629         headless_shell_surface_t *hs_surface = (headless_shell_surface_t *)wl_resource_get_user_data(res_tzvis);
630
631         PEPPER_CHECK(hs_surface, return, "[SHELL] cannot get headless_shell_surface_t\n");
632         hs_surface->tizen_visibility = NULL;
633 }
634
635 static void
636 tizen_position_cb_destroy(struct wl_client *client, struct wl_resource *res_tzpos)
637 {
638    wl_resource_destroy(res_tzpos);
639 }
640
641 static void
642 tizen_position_cb_set(struct wl_client *client, struct wl_resource *res_tzpos, int32_t x, int32_t y)
643 {
644 }
645
646 static const struct tizen_position_interface tizen_position =
647 {
648    tizen_position_cb_destroy,
649    tizen_position_cb_set,
650 };
651
652 static void
653 tizen_position_cb_pos_destroy(struct wl_resource *res_tzpos)
654 {
655 }
656
657 static void
658 tizen_policy_cb_vis_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surf)
659 {
660         pepper_surface_t *psurface;
661         headless_shell_surface_t *hs_surface;
662         struct wl_resource *new_res;
663
664         psurface = wl_resource_get_user_data(surf);
665         PEPPER_CHECK(psurface, return, "fail to get pepper_surface_t\n");
666
667         hs_surface = pepper_object_get_user_data((pepper_object_t *)psurface, surf);
668         PEPPER_CHECK(hs_surface, return, "fail to get headless_shell_surface\n");
669
670         new_res = wl_resource_create(client, &tizen_visibility_interface, 5, id);
671         if (!new_res) {
672                 PEPPER_ERROR("fail to create tizen_visibility");
673                 wl_resource_post_no_memory(resource);
674                 return;
675         }
676
677         wl_resource_set_implementation(new_res,
678                         &tizen_visibility,
679                         hs_surface,
680                         tizen_visibility_cb_vis_destroy);
681
682         hs_surface->tizen_visibility = new_res;
683
684         if (hs_surface->visibility != TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED)
685                 tizen_visibility_send_notify(hs_surface->tizen_visibility, hs_surface->visibility);
686 }
687
688 static void
689 tizen_policy_cb_pos_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surf)
690 {
691         struct wl_resource *new_res;
692
693         new_res = wl_resource_create(client, &tizen_position_interface, 1, id);
694         if (!new_res) {
695                 PEPPER_ERROR("fail to create tizen_visibility");
696                 wl_resource_post_no_memory(resource);
697                 return;
698         }
699
700         wl_resource_set_implementation(new_res,
701                         &tizen_position,
702                         NULL,
703                         tizen_position_cb_pos_destroy);
704 }
705
706 static void
707 tizen_policy_cb_activate(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
708 {
709         pepper_surface_t *psurface;
710         headless_shell_surface_t *hs_surface;
711
712         psurface = wl_resource_get_user_data(surf);
713         PEPPER_CHECK(psurface, return, "fail to get pepper_surface_t\n");
714
715         hs_surface = pepper_object_get_user_data((pepper_object_t *)psurface, surf);
716         PEPPER_CHECK(hs_surface, return, "fail to get headless_shell_surface\n");
717         PEPPER_CHECK(hs_surface->view, return, "invalid view from headless_shell_surface\n");
718
719         pepper_view_stack_top(hs_surface->view, PEPPER_TRUE);
720
721         headless_shell_add_idle(hs_surface->hs_shell);
722 }
723
724 static void
725 tizen_policy_cb_activate_below_by_res_id(struct wl_client *client, struct wl_resource *resource,  uint32_t res_id, uint32_t below_res_id)
726 {
727 }
728
729 static void
730 tizen_policy_cb_raise(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
731 {
732 }
733
734 static void
735 tizen_policy_cb_lower(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
736 {
737 }
738
739 static void
740 tizen_policy_cb_lower_by_res_id(struct wl_client *client, struct wl_resource *resource,  uint32_t res_id)
741 {
742 }
743
744 static void
745 tizen_policy_cb_focus_skip_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
746 {
747         pepper_surface_t *psurface;
748         headless_shell_surface_t *hs_surface;
749
750         psurface = wl_resource_get_user_data(surf);
751         PEPPER_CHECK(psurface, return, "fail to get pepper_surface_t\n");
752
753         hs_surface = pepper_object_get_user_data((pepper_object_t *)psurface, surf);
754         PEPPER_CHECK(hs_surface, return, "fail to get headless_shell_surface\n");
755
756         hs_surface->skip_focus = PEPPER_TRUE;
757 }
758
759 static void
760 tizen_policy_cb_focus_skip_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
761 {
762         pepper_surface_t *psurface;
763         headless_shell_surface_t *hs_surface;
764
765         psurface = wl_resource_get_user_data(surf);
766         PEPPER_CHECK(psurface, return, "fail to get pepper_surface_t\n");
767
768         hs_surface = pepper_object_get_user_data((pepper_object_t *)psurface, surf);
769         PEPPER_CHECK(hs_surface, return, "fail to get headless_shell_surface\n");
770
771         hs_surface->skip_focus = PEPPER_FALSE;
772 }
773
774 static void
775 tizen_policy_cb_role_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf, const char *role)
776 {
777 }
778
779 static void
780 tizen_policy_cb_type_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf, uint32_t type)
781 {
782 }
783
784 static void
785 tizen_policy_cb_conformant_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
786 {
787 }
788
789 static void
790 tizen_policy_cb_conformant_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
791 {
792 }
793
794 static void
795 tizen_policy_cb_conformant_get(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
796 {
797    tizen_policy_send_conformant(resource, surf, 0);
798 }
799
800 static void
801 tizen_policy_cb_notilv_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf, int32_t lv)
802 {
803 }
804
805 static void
806 tizen_policy_cb_transient_for_set(struct wl_client *client, struct wl_resource *resource, uint32_t child_id, uint32_t parent_id)
807 {
808 }
809
810 static void
811 tizen_policy_cb_transient_for_unset(struct wl_client *client, struct wl_resource *resource, uint32_t child_id)
812 {
813    tizen_policy_send_transient_for_done(resource, child_id);
814 }
815
816 static void
817 tizen_policy_cb_win_scrmode_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf, uint32_t mode)
818 {
819    tizen_policy_send_window_screen_mode_done
820      (resource, surf, mode, TIZEN_POLICY_ERROR_STATE_NONE);
821 }
822
823 static void
824 tizen_policy_cb_subsurf_place_below_parent(struct wl_client *client, struct wl_resource *resource, struct wl_resource *subsurf)
825 {
826 }
827
828 static void
829 tizen_policy_cb_subsurf_stand_alone_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *subsurf)
830 {
831 }
832
833 static void
834 tizen_policy_cb_subsurface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface, uint32_t parent_id)
835 {
836         wl_client_post_implementation_error(client, "Headless server not support tizen_subsurface\n");
837 }
838
839 static void
840 tizen_policy_cb_opaque_state_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, int32_t state)
841 {
842 }
843
844 static void
845 tizen_policy_cb_iconify(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
846 {
847 }
848
849 static void
850 tizen_policy_cb_uniconify(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
851 {
852 }
853
854 static void
855 tizen_policy_cb_aux_hint_add(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf, int32_t id, const char *name, const char *value)
856 {
857 }
858
859 static void
860 tizen_policy_cb_aux_hint_change(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf, int32_t id, const char *value)
861 {
862 }
863
864 static void
865 tizen_policy_cb_aux_hint_del(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf, int32_t id)
866 {
867 }
868
869 static void
870 tizen_policy_cb_supported_aux_hints_get(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
871 {
872 }
873
874 static void
875 tizen_policy_cb_background_state_set(struct wl_client *client, struct wl_resource *resource, uint32_t pid)
876 {
877 }
878
879 static void
880 tizen_policy_cb_background_state_unset(struct wl_client *client, struct wl_resource *resource, uint32_t pid)
881 {
882 }
883
884 static void
885 tizen_policy_cb_floating_mode_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
886 {
887 }
888
889 static void
890 tizen_policy_cb_floating_mode_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf)
891 {
892 }
893
894 static void
895 tizen_policy_cb_stack_mode_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surf, uint32_t mode)
896 {
897 }
898
899 static void
900 tizen_policy_cb_activate_above_by_res_id(struct wl_client *client, struct wl_resource *resource,  uint32_t res_id, uint32_t above_res_id)
901 {
902 }
903
904 static void
905 tizen_policy_cb_subsurf_watcher_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface)
906 {
907         wl_client_post_implementation_error(client, "Headless server not support tizen_subsurface\n");
908 }
909
910 static void
911 tizen_policy_cb_parent_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *child, struct wl_resource *parent)
912 {
913 }
914
915 static void
916 tizen_policy_cb_ack_conformant_region(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t serial)
917 {
918 }
919
920 static void
921 tizen_policy_cb_destroy(struct wl_client *client, struct wl_resource *resource)
922 {
923    wl_resource_destroy(resource);
924 }
925
926 static void
927 tizen_policy_cb_has_video(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t has)
928 {
929 }
930
931 static const struct tizen_policy_interface tizen_policy_iface =
932 {
933    tizen_policy_cb_vis_get,
934    tizen_policy_cb_pos_get,
935    tizen_policy_cb_activate,
936    tizen_policy_cb_activate_below_by_res_id,
937    tizen_policy_cb_raise,
938    tizen_policy_cb_lower,
939    tizen_policy_cb_lower_by_res_id,
940    tizen_policy_cb_focus_skip_set,
941    tizen_policy_cb_focus_skip_unset,
942    tizen_policy_cb_role_set,
943    tizen_policy_cb_type_set,
944    tizen_policy_cb_conformant_set,
945    tizen_policy_cb_conformant_unset,
946    tizen_policy_cb_conformant_get,
947    tizen_policy_cb_notilv_set,
948    tizen_policy_cb_transient_for_set,
949    tizen_policy_cb_transient_for_unset,
950    tizen_policy_cb_win_scrmode_set,
951    tizen_policy_cb_subsurf_place_below_parent,
952    tizen_policy_cb_subsurf_stand_alone_set,
953    tizen_policy_cb_subsurface_get,
954    tizen_policy_cb_opaque_state_set,
955    tizen_policy_cb_iconify,
956    tizen_policy_cb_uniconify,
957    tizen_policy_cb_aux_hint_add,
958    tizen_policy_cb_aux_hint_change,
959    tizen_policy_cb_aux_hint_del,
960    tizen_policy_cb_supported_aux_hints_get,
961    tizen_policy_cb_background_state_set,
962    tizen_policy_cb_background_state_unset,
963    tizen_policy_cb_floating_mode_set,
964    tizen_policy_cb_floating_mode_unset,
965    tizen_policy_cb_stack_mode_set,
966    tizen_policy_cb_activate_above_by_res_id,
967    tizen_policy_cb_subsurf_watcher_get,
968    tizen_policy_cb_parent_set,
969    tizen_policy_cb_ack_conformant_region,
970    tizen_policy_cb_destroy,
971    tizen_policy_cb_has_video,
972 };
973
974 static void
975 tizen_policy_cb_unbind(struct wl_resource *resource)
976 {
977         headless_shell_t *shell = (headless_shell_t *)wl_resource_get_user_data(resource);
978
979         if (shell)
980                 shell->tizen_policy = NULL;
981 }
982
983 static void
984 tizen_policy_cb_bind(struct wl_client *client, void *data, uint32_t ver, uint32_t id)
985 {
986         headless_shell_t *shell = (headless_shell_t *)data;
987         struct wl_resource *resource;
988
989         PEPPER_CHECK(shell, goto err, "data is NULL\n");
990
991         resource = wl_resource_create(client,
992                                                                         &tizen_policy_interface,
993                                                                         ver,
994                                                                         id);
995         PEPPER_CHECK(resource, goto err, "fail to create tizen_policy\n");
996
997         wl_resource_set_implementation(resource,
998                                                                         &tizen_policy_iface,
999                                                                         shell,
1000                                                                         tizen_policy_cb_unbind);
1001         return;
1002
1003 err:
1004         wl_client_post_no_memory(client);
1005 }
1006
1007 static pepper_bool_t
1008 tizen_policy_init(headless_shell_t *shell)
1009 {
1010         struct wl_display *display;
1011
1012         display = pepper_compositor_get_display(shell->compositor);
1013
1014         shell->tizen_policy = wl_global_create(display, &tizen_policy_interface, 7, shell, tizen_policy_cb_bind);
1015         PEPPER_CHECK(shell->tizen_policy, return PEPPER_FALSE, "faile to create tizen_policy\n");
1016
1017         return PEPPER_TRUE;
1018 }
1019
1020 void
1021 tizen_policy_deinit(headless_shell_t *shell)
1022 {
1023         if (shell->tizen_policy)
1024                 wl_global_destroy(shell->tizen_policy);
1025 }
1026
1027 static void
1028 headless_shell_send_visiblity(pepper_view_t *view, uint8_t visibility)
1029 {
1030         pepper_surface_t *surface;
1031         headless_shell_surface_t *hs_surface;
1032
1033         if (view == NULL) return;
1034
1035         surface = pepper_view_get_surface(view);
1036         PEPPER_CHECK(surface, return, "[SHELL] Invalid object surface:%p\n", surface);
1037
1038         hs_surface = pepper_object_get_user_data((pepper_object_t *)surface, pepper_surface_get_resource(surface));
1039         PEPPER_CHECK(hs_surface, return, "[SHELL] Invalid object headless_surface:%p\n", hs_surface);
1040
1041         if (hs_surface->visibility == visibility) {
1042                 PEPPER_TRACE("[SHELL] Same Visibility hs_surface:%p, visibility:%d\n", hs_surface, visibility);
1043                 return;
1044         }
1045
1046         if (hs_surface->tizen_visibility)
1047                 tizen_visibility_send_notify(hs_surface->tizen_visibility, visibility);
1048
1049         hs_surface->visibility = visibility;
1050         PEPPER_TRACE("[SHELL] Set Visibility hs_surface:%p, visibility:%d\n", hs_surface, visibility);
1051 }
1052
1053 static void
1054 headless_shell_cb_idle(void *data)
1055 {
1056         headless_shell_t *hs_shell = (headless_shell_t *)data;
1057         const pepper_list_t *list;
1058         pepper_list_t *l = NULL;
1059         pepper_view_t *view;
1060         pepper_surface_t *surface;
1061         headless_shell_surface_t *hs_surface;
1062
1063         pepper_view_t *focus = NULL, *top = NULL, *top_visible = NULL;
1064
1065         PEPPER_TRACE("[SHELL] Enter Idle\n");
1066         list = pepper_compositor_get_view_list(hs_shell->compositor);
1067
1068         pepper_list_for_each_list(l,  list) {
1069                 if (!l) break;
1070
1071                 view = (pepper_view_t *)l->item;
1072                 PEPPER_CHECK(view, continue, "[SHELL] idle_cb, Invalid object view:%p\n", view);
1073
1074                 surface = pepper_view_get_surface(view);
1075                 PEPPER_CHECK(surface, continue, "[SHELL] idle_cb, Invalid object surface:%p\n", surface);
1076
1077                 hs_surface = pepper_object_get_user_data((pepper_object_t *)surface, pepper_surface_get_resource(surface));
1078                 PEPPER_CHECK(hs_surface, continue, "[SHELL] idle_cb, Invalid object headless_surface:%p\n", hs_surface);
1079
1080                 if (!pepper_view_is_mapped(view)) {
1081                         headless_shell_send_visiblity(view, TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED);
1082                         continue;
1083                 }
1084
1085                 if (!top)
1086                         top = view;
1087
1088                 if (!focus && !hs_surface->skip_focus)
1089                         focus = view;
1090
1091                 if (!top_visible && pepper_surface_get_buffer(surface))
1092                         top_visible = view;
1093
1094                 if (top && focus && top_visible)
1095                         break;
1096         }
1097
1098         if (top != hs_shell->top_mapped) {
1099                 const pepper_list_t *l;
1100                 pepper_list_t *ll;
1101
1102                 PEPPER_TRACE("[SHELL] IDLE : top-view change: %p to %p\n", hs_shell->top_mapped , top);
1103                 hs_shell->top_mapped = top;
1104                 headless_input_set_top_view(hs_shell->compositor, hs_shell->top_mapped);
1105                 headless_debug_set_top_view(hs_shell->compositor, hs_shell->top_mapped);
1106
1107                 /*Force update the output*/
1108                 l = pepper_compositor_get_output_list(hs_shell->compositor);
1109                 pepper_list_for_each_list(ll, l) {
1110                         pepper_output_add_damage_region((pepper_output_t *)ll->item, NULL);
1111                 }
1112         }
1113
1114         if (focus != hs_shell->focus) {
1115                 PEPPER_TRACE("[SHELL] IDLE : focus-view change: %p to %p\n", hs_shell->focus , focus);
1116                 hs_shell->focus = focus;
1117                 headless_input_set_focus_view(hs_shell->compositor, hs_shell->focus);
1118                 headless_debug_set_focus_view(hs_shell->compositor, hs_shell->focus);
1119         }
1120
1121         if (top_visible != hs_shell->top_visible) {
1122                 PEPPER_TRACE("[SHELL] IDLE : visible-view change: %p to %p\n", hs_shell->top_visible, top_visible);
1123                 headless_shell_send_visiblity(hs_shell->top_visible, TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED);
1124                 headless_shell_send_visiblity(top_visible, TIZEN_VISIBILITY_VISIBILITY_UNOBSCURED);
1125                 hs_shell->top_visible = top_visible;
1126         }
1127
1128         hs_shell->cb_idle = NULL;
1129 }
1130
1131 static void
1132 headless_shell_cb_surface_commit(pepper_event_listener_t *listener,
1133                                                                                 pepper_object_t *object,
1134                                                                                 uint32_t id, void *info, void *data)
1135 {
1136         headless_shell_surface_t * hs_surface = (headless_shell_surface_t *)data;
1137
1138         PEPPER_CHECK(((pepper_object_t *)hs_surface->surface == object), return, "Invalid object\n");
1139
1140         /*TODO
1141         1. Check the changes(buffer, map status...)
1142         */
1143         if (IS_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE)) {
1144                 if (hs_surface->surface_type != HEADLESS_SURFACE_NONE)
1145                         pepper_view_map(hs_surface->view);
1146                 else
1147                         pepper_view_unmap(hs_surface->view);
1148
1149                 PEPPER_TRACE("Surface type change. view:%p, type:%d, res:%p\n", hs_surface->view, hs_surface->surface_type, hs_surface->zxdg_surface);
1150         }
1151
1152         hs_surface->updates = 0;
1153
1154         headless_shell_add_idle(hs_surface->hs_shell);
1155 }
1156
1157 static void
1158 headless_shell_cb_surface_free(void *data)
1159 {
1160         headless_shell_surface_t *surface = (headless_shell_surface_t *)data;
1161
1162         PEPPER_TRACE("[SHELL] hs_surface free surface:%p, view:%p, zxdg_shell_surface:%p, zxdg_surface:%p\n",
1163                                         surface->surface, surface->view,
1164                                         surface->zxdg_shell_surface, surface->zxdg_surface);
1165
1166         free(surface);
1167 }
1168
1169 static void
1170 headless_shell_cb_surface_add(pepper_event_listener_t *listener,
1171                                                                                 pepper_object_t *object,
1172                                                                                 uint32_t id, void *info, void *data)
1173 {
1174         headless_shell_surface_t *hs_surface;
1175         pepper_surface_t *surface = (pepper_surface_t *)info;
1176
1177         hs_surface = (headless_shell_surface_t*)calloc(sizeof(headless_shell_surface_t), 1);
1178         PEPPER_CHECK(hs_surface, return, "fail to alloc for headless_shell_surface\n");
1179
1180         hs_surface->hs_shell = (headless_shell_t *)data;
1181         hs_surface->surface = (pepper_surface_t *)surface;
1182         hs_surface->visibility = TIZEN_VISIBILITY_VISIBILITY_FULLY_OBSCURED;
1183
1184         pepper_object_set_user_data((pepper_object_t *)surface,
1185                                                                 pepper_surface_get_resource(surface),
1186                                                                 hs_surface,
1187                                                                 headless_shell_cb_surface_free);
1188         PEPPER_TRACE("[SHELL] surface_Add: pepper_surface:%, headless_shell:%p to p\n", surface, hs_surface);
1189 }
1190
1191 static void
1192 headless_shell_cb_surface_remove(pepper_event_listener_t *listener,
1193                                                                                 pepper_object_t *object,
1194                                                                                 uint32_t id, void *info, void *data)
1195 {
1196         headless_shell_surface_t *hs_surface;
1197         pepper_surface_t *surface = (pepper_surface_t *)info;
1198
1199         hs_surface = pepper_object_get_user_data((pepper_object_t *)surface, pepper_surface_get_resource(surface));
1200         PEPPER_CHECK(hs_surface, return, "[SHELL] cb_surface_remove, Invalid object headless_surface:%p\n", hs_surface);
1201         PEPPER_TRACE("[SHELL] surface_remove: pepper_surface:%p, headless_shell:%p\n", object, hs_surface);
1202
1203         if (hs_surface->zxdg_surface) {
1204                 wl_resource_set_user_data(hs_surface->zxdg_surface, NULL);
1205                 hs_surface->zxdg_surface = NULL;
1206         }
1207
1208         if (hs_surface->zxdg_shell_surface) {
1209                 wl_resource_set_user_data(hs_surface->zxdg_shell_surface, NULL);
1210                 hs_surface->zxdg_shell_surface = NULL;
1211         }
1212
1213         if (hs_surface->view) {
1214                 pepper_view_destroy(hs_surface->view);
1215                 hs_surface->view = NULL;
1216         }
1217
1218         SET_UPDATE(hs_surface->updates, UPDATE_SURFACE_TYPE);
1219         headless_shell_add_idle(hs_surface->hs_shell);
1220 }
1221
1222 static void
1223 headless_shell_cb_view_remove(pepper_event_listener_t *listener,
1224                                                                                 pepper_object_t *object,
1225                                                                                 uint32_t id, void *info, void *data)
1226 {
1227         pepper_view_t *view = (pepper_view_t *)info;
1228         headless_shell_t *shell = (headless_shell_t *)data;
1229
1230         if (view == shell->top_mapped)
1231                 shell->top_mapped = NULL;
1232
1233         if (view == shell->top_visible)
1234                 shell->top_visible = NULL;
1235
1236         if (view == shell->focus)
1237                 shell->focus = NULL;
1238
1239         headless_shell_add_idle(shell);
1240 }
1241
1242 static void
1243 headless_shell_add_idle(headless_shell_t *shell)
1244 {
1245         struct wl_event_loop *loop;
1246
1247         if (!shell || shell->cb_idle)
1248                 return;
1249
1250         loop = wl_display_get_event_loop(pepper_compositor_get_display(shell->compositor));
1251         PEPPER_CHECK(loop, return, "fail to get event loop\n");
1252
1253         shell->cb_idle = wl_event_loop_add_idle(loop, headless_shell_cb_idle, shell);
1254         PEPPER_CHECK(shell->cb_idle, return, "fail to add idle\n");
1255 }
1256
1257 static void
1258 headless_shell_init_listeners(headless_shell_t *shell)
1259 {
1260         shell->surface_add_listener = pepper_object_add_event_listener((pepper_object_t *)shell->compositor,
1261                                                                                                                                         PEPPER_EVENT_COMPOSITOR_SURFACE_ADD,
1262                                                                                                                                         0, headless_shell_cb_surface_add, shell);
1263
1264         shell->surface_remove_listener = pepper_object_add_event_listener((pepper_object_t *)shell->compositor,
1265                                                                                                                                                 PEPPER_EVENT_COMPOSITOR_SURFACE_REMOVE,
1266                                                                                                                                                 0, headless_shell_cb_surface_remove, shell);
1267
1268         shell->view_remove_listener = pepper_object_add_event_listener((pepper_object_t *)shell->compositor,
1269                                                                                                                                                 PEPPER_EVENT_COMPOSITOR_VIEW_REMOVE,
1270                                                                                                                                                 0, headless_shell_cb_view_remove, shell);
1271 }
1272
1273 static void
1274 headless_shell_deinit_listeners(headless_shell_t *shell)
1275 {
1276         pepper_event_listener_remove(shell->surface_add_listener);
1277         pepper_event_listener_remove(shell->surface_remove_listener);
1278         pepper_event_listener_remove(shell->view_remove_listener);
1279 }
1280
1281 static void
1282 headless_shell_destroy(headless_shell_t *shell)
1283 {
1284         if (!shell)
1285                 return;
1286
1287         if (shell->cb_idle)
1288                 wl_event_source_remove(shell->cb_idle);
1289
1290         headless_shell_deinit_listeners(shell);
1291         zxdg_deinit(shell);
1292         tizen_policy_deinit(shell);
1293 }
1294
1295 void
1296 headless_shell_deinit(pepper_compositor_t *compositor)
1297 {
1298         headless_shell_t *shell;
1299
1300         PEPPER_CHECK(compositor, return, "compositor is NULL\n");
1301
1302         shell = (headless_shell_t *)pepper_object_get_user_data((pepper_object_t *)compositor, &KEY_SHELL);
1303         PEPPER_CHECK(shell, return, "shell is NULL\n");
1304
1305         headless_shell_destroy(shell);
1306
1307         pepper_object_set_user_data((pepper_object_t *)shell->compositor, &KEY_SHELL, NULL, NULL);
1308         free(shell);
1309 }
1310
1311 pepper_bool_t
1312 headless_shell_init(pepper_compositor_t *compositor)
1313 {
1314         headless_shell_t *shell;
1315
1316         shell = (headless_shell_t*)calloc(sizeof(headless_shell_t), 1);
1317         PEPPER_CHECK(shell, goto error, "fail to alloc for shell\n");
1318         shell->compositor = compositor;
1319
1320         headless_shell_init_listeners(shell);
1321         PEPPER_CHECK(zxdg_init(shell), goto error, "zxdg_init() failed\n");
1322         PEPPER_CHECK(tizen_policy_init(shell), goto error, "tizen_policy_init() failed\n");
1323
1324         pepper_object_set_user_data((pepper_object_t *)compositor, &KEY_SHELL, shell, NULL);
1325
1326         return PEPPER_TRUE;
1327
1328 error:
1329         if (shell) {
1330                 headless_shell_destroy(shell);
1331                 free(shell);
1332         }
1333         return PEPPER_FALSE;
1334 }