Fix bug about updating window information
[platform/core/appfw/app-core.git] / src / appcore-efl.c
1 /*
2  * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <sys/un.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <stdarg.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <stdlib.h>
26
27 #if defined(WAYLAND)
28 #include <Ecore_Wayland.h>
29 #include <wayland-client.h>
30 #include <wayland-tbm-client.h>
31 #include <tizen-extension-client-protocol.h>
32 #elif defined(X11)
33 #include <X11/Xatom.h>
34 #include <X11/Xlib.h>
35 #include <Ecore_X.h>
36 #endif
37
38 #include <Ecore.h>
39 #include <Ecore_Evas.h>
40 #include <Ecore_Input_Evas.h>
41 #include <Elementary.h>
42 #include <glib-object.h>
43 #include <malloc.h>
44 #include <glib.h>
45 #include <gio/gio.h>
46 #include <stdbool.h>
47 #include <aul.h>
48 #include <aul_svc.h>
49 #include <bundle_internal.h>
50 #include <ttrace.h>
51
52 #include "appcore-internal.h"
53 #include "appcore-efl.h"
54
55 static pid_t _pid;
56 static bool resource_reclaiming = TRUE;
57 static int tmp_val = 0;
58
59 struct ui_priv {
60         const char *name;
61         enum app_state state;
62
63         Ecore_Event_Handler *hshow;
64         Ecore_Event_Handler *hhide;
65         Ecore_Event_Handler *hvchange;
66 #if defined(WAYLAND)
67         Ecore_Event_Handler *hlower;
68 #endif
69         Ecore_Event_Handler *hcmsg; /* WM_ROTATE */
70
71         Ecore_Timer *mftimer; /* Ecore Timer for memory flushing */
72
73         struct appcore *app_core;
74 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
75         void (*prepare_to_suspend) (void *data);
76         void (*exit_from_suspend) (void *data);
77 #endif
78         struct appcore_ops *ops;
79         void (*mfcb) (void); /* Memory Flushing Callback */
80
81         /* WM_ROTATE */
82         int wm_rot_supported;
83         int rot_started;
84         int (*rot_cb) (void *event_info, enum appcore_rm, void *);
85         void *rot_cb_data;
86         enum appcore_rm rot_mode;
87         bundle *pending_data;
88         char *below_app;
89 };
90
91 static struct ui_priv priv;
92
93 static const char *_ae_name[AE_MAX] = {
94         [AE_UNKNOWN] = "UNKNOWN",
95         [AE_CREATE] = "CREATE",
96         [AE_TERMINATE] = "TERMINATE",
97         [AE_PAUSE] = "PAUSE",
98         [AE_RESUME] = "RESUME",
99         [AE_RESET] = "RESET",
100         [AE_LOWMEM_POST] = "LOWMEM_POST",
101         [AE_MEM_FLUSH] = "MEM_FLUSH",
102         [AE_UPDATE_REQUESTED] = "UPDATE_REQUESTED",
103 };
104
105 static const char *_as_name[] = {
106         [AS_NONE] = "NONE",
107         [AS_CREATED] = "CREATED",
108         [AS_RUNNING] = "RUNNING",
109         [AS_PAUSED] = "PAUSED",
110         [AS_DYING] = "DYING",
111 };
112
113 static bool b_active = FALSE;
114 static bool first_launch = TRUE;
115
116 struct win_node {
117         unsigned int win;
118 #if defined(WAYLAND)
119         unsigned int surf;
120 #endif
121         bool bfobscured;
122 };
123
124 #if defined(X11)
125 static struct ui_wm_rotate wm_rotate;
126 #endif
127 static Eina_Bool __visibility_cb(void *data, int type, void *event);
128 static GSList *g_winnode_list;
129
130 static struct wl_display *dsp;
131 static struct wl_registry *reg;
132 static struct tizen_policy *tz_policy;
133 static bool bg_state = false;
134
135 static void __wl_listener_cb(void *data, struct wl_registry *reg,
136                 uint32_t id, const char *interface, uint32_t ver)
137 {
138         if (interface && !strcmp(interface, "tizen_policy")) {
139                 if (!tz_policy)
140                         tz_policy = wl_registry_bind(reg, id,
141                                         &tizen_policy_interface, 1);
142         }
143 }
144
145 static void __wl_listener_remove_cb(void *data, struct wl_registry *reg,
146                 unsigned int id)
147 {
148         /* do nothing */
149 }
150
151 static const struct wl_registry_listener reg_listener = {
152         __wl_listener_cb,
153         __wl_listener_remove_cb
154 };
155
156 static int __init_wl(void)
157 {
158         _DBG("initialize wayland");
159         dsp = wl_display_connect(NULL);
160         if (dsp == NULL) {
161                 _ERR("Failed to connect wl display");
162                 return -1;
163         }
164
165         reg = wl_display_get_registry(dsp);
166         if (reg == NULL) {
167                 _ERR("Failed to get registry");
168                 wl_display_disconnect(dsp);
169                 return -1;
170         }
171
172         wl_registry_add_listener(reg, &reg_listener, NULL);
173         wl_display_roundtrip(dsp);
174
175         if (!tz_policy) {
176                 _ERR("Failed to get tizen policy interface");
177                 wl_registry_destroy(reg);
178                 wl_display_disconnect(dsp);
179                 return -1;
180         }
181
182         return 0;
183 }
184
185 static void __finish_wl(void)
186 {
187         if (tz_policy) {
188                 tizen_policy_destroy(tz_policy);
189                 tz_policy = NULL;
190         }
191
192         if (reg) {
193                 wl_registry_destroy(reg);
194                 reg = NULL;
195         }
196
197         if (dsp) {
198                 wl_display_disconnect(dsp);
199                 dsp = NULL;
200         }
201 }
202
203 static void __set_bg_state(void)
204 {
205         if (__init_wl() < 0)
206                 return;
207
208         tizen_policy_set_background_state(tz_policy, getpid());
209         wl_display_roundtrip(dsp);
210         bg_state = true;
211         _DBG("bg state: %d", bg_state);
212 }
213
214 static void __unset_bg_state(void)
215 {
216         if (!tz_policy)
217                 return;
218
219         tizen_policy_unset_background_state(tz_policy, getpid());
220         wl_display_roundtrip(dsp);
221         bg_state = false;
222         _DBG("bg state: %d", bg_state);
223         __finish_wl();
224 }
225
226 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
227 static void __appcore_efl_prepare_to_suspend(void *data)
228 {
229         struct ui_priv *ui = (struct ui_priv *)data;
230         struct sys_op *op = NULL;
231         int suspend = APPCORE_SUSPENDED_STATE_WILL_ENTER_SUSPEND;
232
233         if (ui->app_core && !ui->app_core->allowed_bg && !ui->app_core->suspended_state) {
234                 op = &ui->app_core->sops[SE_SUSPENDED_STATE];
235                 if (op && op->func)
236                         op->func((void *)&suspend, op->data); /* calls c-api handler */
237
238                 ui->app_core->suspended_state = true;
239         }
240         _DBG("[__SUSPEND__]");
241 }
242
243 static void __appcore_efl_exit_from_suspend(void *data)
244 {
245         struct ui_priv *ui = (struct ui_priv *)data;
246         struct sys_op *op = NULL;
247         int suspend = APPCORE_SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
248
249         if (ui->app_core && !ui->app_core->allowed_bg && ui->app_core->suspended_state) {
250                 op = &ui->app_core->sops[SE_SUSPENDED_STATE];
251                 if (op && op->func)
252                         op->func((void *)&suspend, op->data); /* calls c-api handler */
253
254                 ui->app_core->suspended_state = false;
255         }
256         _DBG("[__SUSPEND__]");
257 }
258 #endif
259
260 static void __appcore_efl_update_requested(void *data)
261 {
262         struct ui_priv *ui = (struct ui_priv *)data;
263         struct sys_op *op;
264         int dummy = 0;
265
266         if (ui->app_core) {
267                 op = &ui->app_core->sops[SE_UPDATE_REQUESTED];
268                 if (op && op->func)
269                         op->func((void *)&dummy, op->data);
270         }
271         _DBG("[__UPDATE_REQUESTED__]");
272 }
273
274 #if defined(MEMORY_FLUSH_ACTIVATE)
275 static Eina_Bool __appcore_memory_flush_cb(void *data)
276 {
277         struct ui_priv *ui = (struct ui_priv *)data;
278
279         appcore_flush_memory();
280         if (ui)
281                 ui->mftimer = NULL;
282
283 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
284         if (ui && ui->prepare_to_suspend) {
285                 _DBG("[__SUSPEND__] flush case");
286                 ui->prepare_to_suspend(ui);
287         }
288 #endif
289
290         return ECORE_CALLBACK_CANCEL;
291 }
292
293 static int __appcore_low_memory_post_cb(struct ui_priv *ui)
294 {
295         if (ui->state == AS_PAUSED)
296                 appcore_flush_memory();
297         else
298                 malloc_trim(0);
299
300         return 0;
301 }
302
303 static void __appcore_timer_add(struct ui_priv *ui)
304 {
305         ui->mftimer = ecore_timer_add(5, __appcore_memory_flush_cb, ui);
306 }
307
308 static void __appcore_timer_del(struct ui_priv *ui)
309 {
310         if (ui->mftimer) {
311                 ecore_timer_del(ui->mftimer);
312                 ui->mftimer = NULL;
313         }
314 }
315
316 #else
317
318 static int __appcore_low_memory_post_cb(ui_priv *ui)
319 {
320         return -1;
321 }
322
323 #define __appcore_timer_add(ui) 0
324 #define __appcore_timer_del(ui) 0
325
326 #endif
327
328 static void __appcore_efl_memory_flush_cb(void)
329 {
330         _DBG("[APP %d]   __appcore_efl_memory_flush_cb()", _pid);
331         elm_cache_all_flush();
332 }
333 #if defined(WAYLAND)
334 static void wl_raise_win(void)
335 {
336         Ecore_Wl_Window *win;
337         unsigned int win_id = appcore_get_main_window();
338
339         _DBG("Raise window: %d", win_id);
340         win = ecore_wl_window_find(win_id);
341         ecore_wl_window_activate(win);
342 }
343
344 static void wl_pause_win(void)
345 {
346         Ecore_Wl_Window *win;
347         GSList *wlist = g_winnode_list;
348         struct win_node *entry = NULL;
349
350         _DBG("Pause window");
351
352         while (wlist) {
353                 entry = wlist->data;
354
355                 _DBG("Pause window: %d", entry->win);
356                 win = ecore_wl_window_find(entry->win);
357                 ecore_wl_window_iconified_set(win, EINA_TRUE);
358
359                 wlist = wlist->next;
360         }
361 }
362
363 #endif
364
365 static void __do_app(enum app_event event, void *data, bundle * b)
366 {
367         int r = -1;
368         struct ui_priv *ui = data;
369         const char *below_app;
370         const char *bg_launch;
371
372         _DBG("[APP %d] Event: %d", _pid, event);
373         _ret_if(ui == NULL || event >= AE_MAX);
374         _DBG("[APP %d] Event: %s State: %s", _pid, _ae_name[event],
375              _as_name[ui->state]);
376
377         if (event == AE_MEM_FLUSH) {
378                 ui->mfcb();
379                 return;
380         }
381
382         if (event == AE_LOWMEM_POST) {
383                 if (__appcore_low_memory_post_cb(ui) == 0)
384                         return;
385         }
386
387         if (!(ui->state == AS_PAUSED && event == AE_PAUSE))
388                 __appcore_timer_del(ui);
389
390         if (ui->state == AS_DYING) {
391                 _ERR("Skip the event in dying state");
392                 return;
393         }
394
395         if (event == AE_TERMINATE) {
396                 _DBG("[APP %d] TERMINATE", _pid);
397                 elm_exit();
398                 aul_status_update(STATUS_DYING);
399                 return;
400         }
401
402         if (event == AE_RAISE) {
403 #if defined(X11)
404                 x_raise_win(getpid());
405 #elif defined(WAYLAND)
406                 wl_raise_win();
407 #endif
408                 return;
409         }
410
411         if (event == AE_LOWER) {
412 #if defined(X11)
413                 x_pause_win(getpid());
414 #elif defined(WAYLAND)
415                 wl_pause_win();
416 #endif
417                 return;
418         }
419
420         _ret_if(ui->ops == NULL);
421
422         switch (event) {
423         case AE_RESET:
424                 _DBG("[APP %d] RESET", _pid);
425                 if (ui->pending_data)
426                         bundle_free(ui->pending_data);
427                 ui->pending_data = bundle_dup(b);
428                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]", ui->name);
429
430                 if (ui->below_app) {
431                         free(ui->below_app);
432                         ui->below_app = NULL;
433                 }
434
435                 below_app = bundle_get_val(b, AUL_SVC_K_RELOCATE_BELOW);
436                 if (below_app)
437                         ui->below_app = strdup(below_app);
438 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
439                 if (ui->exit_from_suspend) {
440                         _DBG("[__SUSPEND__] reset case");
441                         ui->exit_from_suspend(ui);
442                 }
443 #endif
444
445                 if (ui->ops->reset) {
446                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
447                                         "APPCORE:RESET");
448                         r = ui->ops->reset(b, ui->ops->data);
449                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
450                 }
451                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", ui->name);
452
453                 if (first_launch) {
454 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
455                         if (ui->app_core->allowed_bg)
456                                 __appcore_timer_add(ui);
457 #endif
458                         first_launch = FALSE;
459                 } else {
460                         _INFO("[APP %d] App already running, raise the window", _pid);
461                         if (bg_state) {
462                                 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
463                                 if (!bg_launch || strcmp(bg_launch, "enable"))
464                                         __unset_bg_state();
465                         }
466 #ifdef X11
467                         x_raise_win(getpid());
468 #else
469                         wl_raise_win();
470 #endif
471                 }
472                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]",
473                     ui->name);
474                 break;
475         case AE_PAUSE:
476                 if (ui->state == AS_RUNNING) {
477                         _DBG("[APP %d] PAUSE", _pid);
478                         if (ui->ops->pause) {
479                                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
480                                                 "APPCORE:PAUSE");
481                                 r = ui->ops->pause(ui->ops->data);
482                                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
483                         }
484                         ui->state = AS_PAUSED;
485                         if (r >= 0 && resource_reclaiming == TRUE)
486                                 __appcore_timer_add(ui);
487 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
488                         else if (r >= 0 && resource_reclaiming == FALSE
489                                         && ui->prepare_to_suspend) {
490                                 _DBG("[__SUSPEND__] pause case");
491                                 ui->prepare_to_suspend(ui);
492                         }
493 #endif
494                 }
495                 /* TODO : rotation stop */
496                 /* r = appcore_pause_rotation_cb(); */
497                 aul_status_update(STATUS_BG);
498                 break;
499         case AE_RESUME:
500                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]",
501                                 ui->name);
502 #ifdef _APPFW_FEATURE_BACKGROUND_MANAGEMENT
503                 if (ui->exit_from_suspend) {
504                         _DBG("[__SUSPEND__] resume case");
505                         ui->exit_from_suspend(ui);
506                 }
507                 if (ui->app_core->allowed_bg)
508                         __appcore_timer_del(ui);
509 #endif
510
511                 if (ui->state == AS_PAUSED || ui->state == AS_CREATED) {
512                         _DBG("[APP %d] RESUME", _pid);
513
514                         if (ui->state == AS_CREATED) {
515                                 bundle_free(ui->pending_data);
516                                 ui->pending_data = NULL;
517                         }
518
519                         if (ui->ops->resume) {
520                                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
521                                         "APPCORE:RESUME");
522                                 ui->ops->resume(ui->ops->data);
523                                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
524                         }
525                         ui->state = AS_RUNNING;
526
527                         if (ui->below_app) {
528                                 aul_app_group_activate_below(ui->below_app);
529                                 free(ui->below_app);
530                                 ui->below_app = NULL;
531                         }
532                 }
533                 /*TODO : rotation start*/
534                 /* r = appcore_resume_rotation_cb(); */
535                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]",
536                     ui->name);
537                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]",
538                     ui->name);
539                 aul_status_update(STATUS_VISIBLE);
540                 break;
541         case AE_TERMINATE_BGAPP:
542                 if (ui->state == AS_PAUSED) {
543                         _DBG("[APP %d] is paused. TERMINATE", _pid);
544                         ui->state = AS_DYING;
545                         aul_status_update(STATUS_DYING);
546                         elm_exit();
547                 } else if (ui->state == AS_RUNNING) {
548                         _DBG("[APP %d] is running.", _pid);
549                 } else {
550                         _DBG("[APP %d] is another state", _pid);
551                 }
552                 break;
553         case AE_UPDATE_REQUESTED:
554                 __appcore_efl_update_requested(ui);
555                 break;
556         default:
557                 /* do nothing */
558                 break;
559         }
560 }
561
562 static struct ui_ops efl_ops = {
563         .data = &priv,
564         .cb_app = __do_app,
565 };
566
567 static bool __check_visible(void)
568 {
569         GSList *iter = NULL;
570         struct win_node *entry = NULL;
571
572         _DBG("[EVENT_TEST][EVENT] __check_visible\n");
573
574         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
575                 entry = iter->data;
576                 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
577                 if (entry->bfobscured == FALSE)
578                         return TRUE;
579         }
580
581         return FALSE;
582 }
583
584 static GSList *__find_win(unsigned int win)
585 {
586         GSList *iter;
587         struct win_node *t;
588
589         for (iter = g_winnode_list; iter; iter = g_slist_next(iter)) {
590                 t = iter->data;
591                 if (t && t->win == win)
592                         return iter;
593         }
594
595         return NULL;
596 }
597
598 #if defined(X11)
599 static bool __add_win(unsigned int win)
600 {
601         struct win_node *t;
602         GSList *f;
603
604         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
605
606         f = __find_win(win);
607         if (f) {
608                 errno = ENOENT;
609                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
610                 return FALSE;
611         }
612
613         t = calloc(1, sizeof(struct win_node));
614         if (t == NULL)
615                 return FALSE;
616
617         t->win = win;
618         t->bfobscured = FALSE;
619
620         g_winnode_list = g_slist_append(g_winnode_list, t);
621
622         return TRUE;
623 }
624 #elif defined(WAYLAND)
625 static bool __add_win(unsigned int win, unsigned int surf)
626 {
627         struct win_node *t;
628         GSList *f;
629
630         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
631
632         f = __find_win(win);
633         if (f) {
634                 errno = ENOENT;
635                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
636                 return FALSE;
637         }
638
639         t = calloc(1, sizeof(struct win_node));
640         if (t == NULL)
641                 return FALSE;
642
643         t->win = win;
644         t->surf = surf;
645         t->bfobscured = FALSE;
646
647         g_winnode_list = g_slist_append(g_winnode_list, t);
648
649         return TRUE;
650 }
651 #endif
652
653 static bool __delete_win(unsigned int win)
654 {
655         GSList *f;
656
657         f = __find_win(win);
658         if (!f) {
659                 errno = ENOENT;
660                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
661                                 win);
662                 return FALSE;
663         }
664
665         free(f->data);
666         g_winnode_list = g_slist_delete_link(g_winnode_list, f);
667
668         return TRUE;
669 }
670
671 #if defined(X11)
672 static bool __update_win(unsigned int win, bool bfobscured)
673 {
674         GSList *f;
675         struct win_node *t;
676
677         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
678              bfobscured);
679
680         f = __find_win(win);
681         if (!f) {
682                 errno = ENOENT;
683                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
684                 return FALSE;
685         }
686
687         t = (struct win_node *)f->data;
688         t->win = win;
689         t->bfobscured = bfobscured;
690
691         return TRUE;
692 }
693 #elif defined(WAYLAND)
694 static bool __update_win(unsigned int win, unsigned int surf, bool bfobscured)
695 {
696         GSList *f;
697         struct win_node *t;
698
699         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
700              bfobscured);
701
702         f = __find_win(win);
703         if (!f) {
704                 errno = ENOENT;
705                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
706                 return FALSE;
707         }
708
709         t = (struct win_node *)f->data;
710         t->win = win;
711         if (surf != 0)
712                 t->surf = surf;
713         t->bfobscured = bfobscured;
714
715         return TRUE;
716 }
717 #endif
718
719 /* WM_ROTATE */
720 #ifdef X11
721 static Ecore_X_Atom _WM_WINDOW_ROTATION_SUPPORTED = 0;
722 static Ecore_X_Atom _WM_WINDOW_ROTATION_CHANGE_REQUEST = 0;
723
724 static int __check_wm_rotation_support(void)
725 {
726         _DBG("Disable window manager rotation");
727         return -1;
728
729         Ecore_X_Window root, win, win2;
730         int ret;
731
732         if (!_WM_WINDOW_ROTATION_SUPPORTED) {
733                 _WM_WINDOW_ROTATION_SUPPORTED =
734                                         ecore_x_atom_get("_E_WINDOW_ROTATION_SUPPORTED");
735         }
736
737         if (!_WM_WINDOW_ROTATION_CHANGE_REQUEST) {
738                 _WM_WINDOW_ROTATION_CHANGE_REQUEST =
739                                         ecore_x_atom_get("_E_WINDOW_ROTATION_CHANGE_REQUEST");
740         }
741
742         root = ecore_x_window_root_first_get();
743         ret = ecore_x_window_prop_xid_get(root,
744                         _WM_WINDOW_ROTATION_SUPPORTED,
745                         ECORE_X_ATOM_WINDOW,
746                         &win, 1);
747         if ((ret == 1) && (win)) {
748                 ret = ecore_x_window_prop_xid_get(win,
749                                 _WM_WINDOW_ROTATION_SUPPORTED,
750                                 ECORE_X_ATOM_WINDOW,
751                                 &win2, 1);
752                 if ((ret == 1) && (win2 == win))
753                         return 0;
754         }
755
756         return -1;
757 }
758
759 static void __set_wm_rotation_support(unsigned int win, unsigned int set)
760 {
761         GSList *iter = NULL;
762         struct win_node *entry = NULL;
763
764         if (win == 0) {
765                 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
766                         entry = iter->data;
767                         if (entry->win) {
768                                 ecore_x_window_prop_card32_set(entry->win,
769                                                 _WM_WINDOW_ROTATION_SUPPORTED,
770                                                 &set, 1);
771                         }
772                 }
773         } else {
774                 ecore_x_window_prop_card32_set(win,
775                                 _WM_WINDOW_ROTATION_SUPPORTED,
776                                 &set, 1);
777         }
778 }
779 #endif
780
781 static Eina_Bool __show_cb(void *data, int type, void *event)
782 {
783 #if defined(WAYLAND)
784         Ecore_Wl_Event_Window_Show *ev;
785
786         ev = event;
787         if (ev->parent_win != 0) {
788                 /* This is child window. Skip!!! */
789                 return ECORE_CALLBACK_PASS_ON;
790         }
791
792         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x, %d\n", ev->win, ev->data[0]);
793
794         if (!__find_win((unsigned int)ev->win))
795                 __add_win((unsigned int)ev->win, (unsigned int)ev->data[0]);
796         else
797                 __update_win((unsigned int)ev->win, (unsigned int)ev->data[0], FALSE);
798
799 #elif defined(X11)
800         Ecore_X_Event_Window_Show *ev;
801
802         ev = event;
803
804         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x\n", ev->win);
805
806         if (!__find_win((unsigned int)ev->win)) {
807                 /* WM_ROTATE */
808                 if ((priv.wm_rot_supported) && (1 == priv.rot_started))
809                         __set_wm_rotation_support(ev->win, 1);
810                 __add_win((unsigned int)ev->win);
811         } else {
812                 __update_win((unsigned int)ev->win, FALSE);
813         }
814 #endif
815
816         appcore_group_attach();
817         return ECORE_CALLBACK_RENEW;
818 }
819
820 static Eina_Bool __hide_cb(void *data, int type, void *event)
821 {
822 #if defined(WAYLAND)
823         Ecore_Wl_Event_Window_Hide *ev;
824 #elif defined(X11)
825         Ecore_X_Event_Window_Hide *ev;
826 #endif
827         int bvisibility = 0;
828
829         ev = event;
830
831         _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
832
833         if (__find_win((unsigned int)ev->win)) {
834                 __delete_win((unsigned int)ev->win);
835                 bvisibility = __check_visible();
836                 if (!bvisibility && b_active == TRUE) {
837                         _DBG(" Go to Pasue state \n");
838                         b_active = FALSE;
839                         __do_app(AE_PAUSE, data, NULL);
840                 }
841         }
842
843         return ECORE_CALLBACK_RENEW;
844 }
845
846 #if defined(WAYLAND)
847 static Eina_Bool __lower_cb(void *data, int type, void *event)
848 {
849         Ecore_Wl_Event_Window_Lower *ev;
850         ev = event;
851         if (!ev) return ECORE_CALLBACK_RENEW;
852         _DBG("ECORE_WL_EVENT_WINDOW_LOWER window id:%u\n", ev->win);
853         appcore_group_lower();
854         return ECORE_CALLBACK_RENEW;
855 }
856 #endif
857
858 static Eina_Bool __visibility_cb(void *data, int type, void *event)
859 {
860 #if defined(WAYLAND)
861         Ecore_Wl_Event_Window_Visibility_Change *ev;
862         int bvisibility = 0;
863         ev = event;
864         __update_win((unsigned int)ev->win, 0, ev->fully_obscured);
865 #elif defined(X11)
866         Ecore_X_Event_Window_Visibility_Change *ev;
867         int bvisibility = 0;
868
869         ev = event;
870
871         __update_win((unsigned int)ev->win, ev->fully_obscured);
872 #endif
873         bvisibility = __check_visible();
874
875         _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
876
877         if (bvisibility && b_active == FALSE) {
878                 _DBG(" Go to Resume state\n");
879                 b_active = TRUE;
880                 __do_app(AE_RESUME, data, NULL);
881
882         } else if (!bvisibility && b_active == TRUE) {
883                 _DBG(" Go to Pasue state \n");
884                 b_active = FALSE;
885                 __do_app(AE_PAUSE, data, NULL);
886         } else
887                 _DBG(" No change state \n");
888
889         return ECORE_CALLBACK_RENEW;
890
891 }
892
893 #if defined(X11)
894 /* WM_ROTATE */
895 static Eina_Bool __cmsg_cb(void *data, int type, void *event)
896 {
897         struct ui_priv *ui = (struct ui_priv *)data;
898         Ecore_X_Event_Client_Message *e = event;
899
900         if (!ui)
901                 return ECORE_CALLBACK_PASS_ON;
902
903         if (e->format != 32)
904                 return ECORE_CALLBACK_PASS_ON;
905
906         if (e->message_type == _WM_WINDOW_ROTATION_CHANGE_REQUEST) {
907                 if ((ui->wm_rot_supported == 0)
908                         || (ui->rot_started == 0)
909                         || (ui->rot_cb == NULL)) {
910                         return ECORE_CALLBACK_PASS_ON;
911                 }
912
913                 enum appcore_rm rm;
914                 switch (e->data.l[1]) {
915                 case 0:
916                         rm = APPCORE_RM_PORTRAIT_NORMAL;
917                         break;
918                 case 90:
919                         rm = APPCORE_RM_LANDSCAPE_REVERSE;
920                         break;
921                 case 180:
922                         rm = APPCORE_RM_PORTRAIT_REVERSE;
923                         break;
924                 case 270:
925                         rm = APPCORE_RM_LANDSCAPE_NORMAL;
926                         break;
927                 default:
928                         rm = APPCORE_RM_UNKNOWN;
929                         break;
930                 }
931
932                 ui->rot_mode = rm;
933
934                 if (APPCORE_RM_UNKNOWN != rm)
935                         ui->rot_cb((void *)&rm, rm, ui->rot_cb_data);
936         }
937
938         return ECORE_CALLBACK_PASS_ON;
939 }
940 #endif
941
942 static void __add_climsg_cb(struct ui_priv *ui)
943 {
944         _ret_if(ui == NULL);
945 #if defined(WAYLAND)
946         ui->hshow =
947                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_SHOW, __show_cb, ui);
948         ui->hhide =
949                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_HIDE, __hide_cb, ui);
950         ui->hvchange =
951                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
952                                 __visibility_cb, ui);
953         ui->hlower =
954                 ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_LOWER,
955                                 __lower_cb, ui);
956 #elif defined(X11)
957         ui->hshow =
958                 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, __show_cb, ui);
959         ui->hhide =
960                 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, __hide_cb, ui);
961         ui->hvchange =
962                 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE,
963                                 __visibility_cb, ui);
964
965         /* Add client message callback for WM_ROTATE */
966         if (!__check_wm_rotation_support()) {
967                 ui->hcmsg = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE,
968                                 __cmsg_cb, ui);
969                 ui->wm_rot_supported = 1;
970                 appcore_set_wm_rotation(&wm_rotate);
971         }
972 #endif
973 }
974
975 static int __before_loop(struct ui_priv *ui, int *argc, char ***argv)
976 {
977         int r;
978         char *hwacc = NULL;
979 #if _APPFW_FEATURE_BACKGROUND_MANAGEMENT
980         struct appcore *ac = NULL;
981 #endif
982         bundle *b;
983         const char *bg_launch;
984
985         if (argc == NULL || argv == NULL) {
986                 _ERR("argc/argv is NULL");
987                 errno = EINVAL;
988                 return -1;
989         }
990
991 #if !(GLIB_CHECK_VERSION(2, 36, 0))
992         g_type_init();
993 #endif
994         elm_init(*argc, *argv);
995
996         hwacc = getenv("HWACC");
997         if (hwacc == NULL) {
998                 _DBG("elm_config_accel_preference_set is not called");
999         } else if (strcmp(hwacc, "USE") == 0) {
1000                 elm_config_accel_preference_set("hw");
1001                 _DBG("elm_config_accel_preference_set : hw");
1002         } else if (strcmp(hwacc, "NOT_USE") == 0) {
1003                 elm_config_accel_preference_set("none");
1004                 _DBG("elm_config_accel_preference_set : none");
1005         } else {
1006                 _DBG("elm_config_accel_preference_set is not called");
1007         }
1008
1009         r = appcore_init(ui->name, &efl_ops, *argc, *argv);
1010         _retv_if(r == -1, -1);
1011
1012 #if _APPFW_FEATURE_BACKGROUND_MANAGEMENT
1013         appcore_get_app_core(&ac);
1014         ui->app_core = ac;
1015         SECURE_LOGD("[__SUSPEND__] appcore initialized, appcore addr: #%x", ac);
1016 #endif
1017
1018         b = bundle_import_from_argv(*argc, *argv);
1019         if (b) {
1020                 bg_launch = bundle_get_val(b, AUL_SVC_K_BG_LAUNCH);
1021                 if (bg_launch && strcmp(bg_launch, "enable") == 0)
1022                         __set_bg_state();
1023
1024                 bundle_free(b);
1025         }
1026
1027         LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:appcore_init:done]", ui->name);
1028         if (ui->ops && ui->ops->create) {
1029                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE");
1030                 r = ui->ops->create(ui->ops->data);
1031                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1032                 if (r < 0) {
1033                         _ERR("create() return error");
1034                         appcore_exit();
1035                         if (ui->ops && ui->ops->terminate) {
1036                                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
1037                                         "APPCORE:TERMINATE");
1038                                 ui->ops->terminate(ui->ops->data);
1039                                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1040                         }
1041                         errno = ECANCELED;
1042                         return -1;
1043                 }
1044                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]",
1045                     ui->name);
1046         }
1047         ui->state = AS_CREATED;
1048
1049         __add_climsg_cb(ui);
1050
1051         return 0;
1052 }
1053
1054 static void __after_loop(struct ui_priv *ui)
1055 {
1056         appcore_unset_rotation_cb();
1057         appcore_exit();
1058
1059         if (ui->state == AS_RUNNING) {
1060                 _DBG("[APP %d] PAUSE before termination", _pid);
1061                 if (ui->ops && ui->ops->pause) {
1062                         traceBegin(TTRACE_TAG_APPLICATION_MANAGER,
1063                                         "APPCORE:PAUSE");
1064                         ui->ops->pause(ui->ops->data);
1065                         traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1066                 }
1067         }
1068
1069         if (ui->ops && ui->ops->terminate) {
1070                 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:TERMINATE");
1071                 ui->ops->terminate(ui->ops->data);
1072                 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1073         }
1074
1075         ui->state = AS_DYING;
1076
1077         if (ui->hshow)
1078                 ecore_event_handler_del(ui->hshow);
1079         if (ui->hhide)
1080                 ecore_event_handler_del(ui->hhide);
1081         if (ui->hvchange)
1082                 ecore_event_handler_del(ui->hvchange);
1083 #if defined(WAYLAND)
1084         if (ui->hlower)
1085                 ecore_event_handler_del(ui->hlower);
1086 #endif
1087
1088         __appcore_timer_del(ui);
1089
1090         elm_shutdown();
1091
1092         /* Check loader case */
1093         if (getenv("AUL_LOADER_INIT")) {
1094                 unsetenv("AUL_LOADER_INIT");
1095                 elm_shutdown();
1096         }
1097 }
1098
1099 static int __set_data(struct ui_priv *ui, const char *name,
1100                     struct appcore_ops *ops)
1101 {
1102         if (ui->name) {
1103                 _ERR("Mainloop already started");
1104                 errno = EINPROGRESS;
1105                 return -1;
1106         }
1107
1108         if (name == NULL || name[0] == '\0') {
1109                 _ERR("Invalid name");
1110                 errno = EINVAL;
1111                 return -1;
1112         }
1113
1114         if (ops == NULL) {
1115                 _ERR("ops is NULL");
1116                 errno = EINVAL;
1117                 return -1;
1118         }
1119
1120         ui->name = strdup(name);
1121         _retv_if(ui->name == NULL, -1);
1122
1123         ui->ops = ops;
1124         ui->mfcb = __appcore_efl_memory_flush_cb;
1125         _pid = getpid();
1126
1127         /* WM_ROTATE */
1128         ui->wm_rot_supported = 0;
1129         ui->rot_started = 0;
1130         ui->rot_cb = NULL;
1131         ui->rot_cb_data = NULL;
1132         ui->rot_mode = APPCORE_RM_UNKNOWN;
1133
1134 #ifdef  _APPFW_FEATURE_BACKGROUND_MANAGEMENT
1135         ui->app_core = NULL;
1136         ui->prepare_to_suspend = __appcore_efl_prepare_to_suspend;
1137         ui->exit_from_suspend = __appcore_efl_exit_from_suspend;
1138 #endif
1139
1140         return 0;
1141 }
1142
1143 static void __unset_data(struct ui_priv *ui)
1144 {
1145         if (ui->name)
1146                 free((void *)ui->name);
1147
1148         memset(ui, 0, sizeof(struct ui_priv));
1149 }
1150
1151 #if defined(X11)
1152 /* WM_ROTATE */
1153 static int __wm_set_rotation_cb(int (*cb) (void *event_info, enum appcore_rm, void *), void *data)
1154 {
1155         if (cb == NULL) {
1156                 errno = EINVAL;
1157                 return -1;
1158         }
1159
1160         if ((priv.wm_rot_supported) && (0 == priv.rot_started))
1161                 __set_wm_rotation_support(0, 1);
1162
1163         priv.rot_cb = cb;
1164         priv.rot_cb_data = data;
1165         priv.rot_started = 1;
1166
1167         return 0;
1168 }
1169
1170 static int __wm_unset_rotation_cb(void)
1171 {
1172         if ((priv.wm_rot_supported) && (1 == priv.rot_started))
1173                 __set_wm_rotation_support(0, 0);
1174
1175         priv.rot_cb = NULL;
1176         priv.rot_cb_data = NULL;
1177         priv.rot_started = 0;
1178
1179         return 0;
1180 }
1181
1182 static int __wm_get_rotation_state(enum appcore_rm *curr)
1183 {
1184         if (curr == NULL) {
1185                 errno = EINVAL;
1186                 return -1;
1187         }
1188
1189         *curr = priv.rot_mode;
1190
1191         return 0;
1192 }
1193
1194 static int __wm_pause_rotation_cb(void)
1195 {
1196         if ((priv.rot_started == 1) && (priv.wm_rot_supported))
1197                 __set_wm_rotation_support(0, 0);
1198
1199         priv.rot_started = 0;
1200
1201         return 0;
1202 }
1203
1204 static int __wm_resume_rotation_cb(void)
1205 {
1206         if ((priv.rot_started == 0) && (priv.wm_rot_supported))
1207                 __set_wm_rotation_support(0, 1);
1208
1209         priv.rot_started = 1;
1210
1211         return 0;
1212 }
1213
1214 static struct ui_wm_rotate wm_rotate = {
1215         __wm_set_rotation_cb,
1216         __wm_unset_rotation_cb,
1217         __wm_get_rotation_state,
1218         __wm_pause_rotation_cb,
1219         __wm_resume_rotation_cb
1220 };
1221 #endif
1222
1223 EXPORT_API int appcore_efl_init(const char *name, int *argc, char ***argv,
1224                      struct appcore_ops *ops)
1225 {
1226         int r;
1227
1228         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", name);
1229
1230         r = __set_data(&priv, name, ops);
1231         _retv_if(r == -1, -1);
1232
1233         r = __before_loop(&priv, argc, argv);
1234         if (r == -1) {
1235                 aul_status_update(STATUS_DYING);
1236                 __unset_data(&priv);
1237                 return -1;
1238         }
1239
1240         return 0;
1241 }
1242
1243 EXPORT_API void appcore_efl_fini(void)
1244 {
1245         aul_status_update(STATUS_DYING);
1246
1247         __after_loop(&priv);
1248
1249         __unset_data(&priv);
1250 }
1251
1252 EXPORT_API int appcore_efl_main(const char *name, int *argc, char ***argv,
1253                                 struct appcore_ops *ops)
1254 {
1255         int r;
1256
1257         r = appcore_efl_init(name, argc, argv, ops);
1258         _retv_if(r == -1, -1);
1259
1260         elm_run();
1261
1262         appcore_efl_fini();
1263
1264         return 0;
1265 }
1266
1267 EXPORT_API int appcore_set_system_resource_reclaiming(bool enable)
1268 {
1269         resource_reclaiming = enable;
1270
1271         return 0;
1272 }
1273
1274 EXPORT_API int appcore_set_app_state(int state)
1275 {
1276         priv.state = state;
1277
1278         tmp_val = 1;
1279
1280         return 0;
1281 }
1282
1283 EXPORT_API int appcore_set_preinit_window_name(const char *win_name)
1284 {
1285         int ret = -1;
1286         void *preinit_window = NULL;
1287         const Evas *e = NULL;
1288
1289         if (!win_name) {
1290                 _ERR("invalid parameter");
1291                 return ret;
1292         }
1293
1294         preinit_window = elm_win_precreated_object_get();
1295         if (!preinit_window) {
1296                 _ERR("Failed to get preinit window");
1297                 return ret;
1298         }
1299
1300         e = evas_object_evas_get((const Evas_Object *)preinit_window);
1301         if (e) {
1302                 Ecore_Evas *ee = ecore_evas_ecore_evas_get(e);
1303                 if (ee) {
1304                         ecore_evas_name_class_set(ee, win_name, win_name);
1305                         ret = 0;
1306                 }
1307         }
1308
1309         return ret;
1310 }
1311
1312 EXPORT_API unsigned int appcore_get_main_window(void)
1313 {
1314         struct win_node *entry = NULL;
1315
1316         if (g_winnode_list != NULL) {
1317                 entry = g_winnode_list->data;
1318                 return (unsigned int) entry->win;
1319         }
1320
1321         return 0;
1322 }
1323
1324 #if defined(WAYLAND)
1325 EXPORT_API unsigned int appcore_get_main_surface(void)
1326 {
1327         struct win_node *entry = NULL;
1328
1329         if (g_winnode_list != NULL) {
1330                 entry = g_winnode_list->data;
1331                 return (unsigned int) entry->surf;
1332         }
1333
1334         return 0;
1335 }
1336 #endif