modify code related to app life-cycle.
[platform/core/appfw/app-core.git] / src / appcore-efl.c
1 /*
2  *  app-core
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <stdarg.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <stdlib.h>
31
32 #ifdef WAYLAND
33 #include <Ecore_Wayland.h>
34 #endif
35
36 #ifdef X11
37 #include <X11/Xatom.h>
38 #include <X11/Xlib.h>
39 #include <Ecore_X.h>
40 #endif
41
42 #include <Ecore.h>
43 #include <Ecore_Evas.h>
44 #include <Ecore_Input_Evas.h>
45 #include <Elementary.h>
46 #include <glib-object.h>
47 #include <malloc.h>
48 #include <glib.h>
49 #include <dbus/dbus.h>
50 #include <stdbool.h>
51 #include <aul.h>
52 #include "appcore-internal.h"
53 #include "appcore-efl.h"
54
55 static pid_t _pid;
56
57 static bool resource_reclaiming = TRUE;
58 static int tmp_val = 0;
59
60 enum proc_status_type { /** cgroup command type **/
61         PROC_STATUS_LAUNCH,
62         PROC_STATUS_RESUME,
63         PROC_STATUS_TERMINATE,
64         PROC_STATUS_FOREGRD,
65         PROC_STATUS_BACKGRD,
66 };
67
68 struct ui_priv {
69         const char *name;
70         enum app_state state;
71
72         Ecore_Event_Handler *hshow;
73         Ecore_Event_Handler *hhide;
74         Ecore_Event_Handler *hvchange;
75         Ecore_Event_Handler *hcmsg; /* WM_ROTATE */
76
77         Ecore_Timer *mftimer;   /* Ecore Timer for memory flushing */
78
79         struct appcore_ops *ops;
80         void (*mfcb) (void);    /* Memory Flushing Callback */
81
82         /* WM_ROTATE */
83         int wm_rot_supported;
84         int rot_started;
85         int (*rot_cb) (void *event_info, enum appcore_rm, void *);
86         void *rot_cb_data;
87         enum appcore_rm rot_mode;
88         bundle *pending_data;
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 };
103
104 static const char *_as_name[] = {
105         [AS_NONE] = "NONE",
106         [AS_CREATED] = "CREATED",
107         [AS_RUNNING] = "RUNNING",
108         [AS_PAUSED] = "PAUSED",
109         [AS_DYING] = "DYING",
110 };
111
112 static bool b_active = FALSE;
113 static bool first_launch = TRUE;
114
115 struct win_node {
116         unsigned int win;
117 #ifdef WAYLAND
118         unsigned int surf;
119 #endif
120         bool bfobscured;
121 };
122
123 static struct ui_wm_rotate wm_rotate;
124 static Eina_Bool __visibility_cb(void *data, int type, void *event);
125
126
127 static void _send_to_resourced(enum proc_status_type type)
128 {
129         DBusConnection *conn;
130         DBusMessage* msg;
131         DBusError dbus_error;
132
133         dbus_error_init(&dbus_error);
134
135         conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
136         if (!conn) {
137                 _ERR("dbus_bus_get failed : [%s]", dbus_error.message);
138                 dbus_error_free(&dbus_error);
139                 return;
140         }
141
142         msg = dbus_message_new_signal("/Org/Tizen/ResourceD/Process",
143                         "org.tizen.resourced.process",
144                         "ProcStatus");
145         if (!msg) {
146                 _ERR("dbus_message_new_signal is failed");
147                 return;
148         }
149
150         if (!dbus_message_append_args(msg,
151                                 DBUS_TYPE_INT32, &type,
152                                 DBUS_TYPE_INT32, &_pid,
153                                 DBUS_TYPE_INVALID)) {
154                 _ERR("dbus_message_append_args is failed. type = %d, pid = %d",
155                                 type, _pid);
156                 dbus_message_unref(msg);
157                 return;
158         }
159
160         if (!dbus_connection_send (conn, msg, NULL)) {
161                 _ERR("dbus_connection_send is failed");
162         }
163
164         dbus_message_unref(msg);
165 }
166
167 static GSList *g_winnode_list;
168
169 #if defined(MEMORY_FLUSH_ACTIVATE)
170 static Eina_Bool __appcore_memory_flush_cb(void *data)
171 {
172         struct ui_priv *ui = (struct ui_priv *)data;
173
174         appcore_flush_memory();
175         ui->mftimer = NULL;
176
177         return ECORE_CALLBACK_CANCEL;
178 }
179
180 static int __appcore_low_memory_post_cb(struct ui_priv *ui)
181 {
182         if (ui->state == AS_PAUSED) {
183                 appcore_flush_memory();
184         } else {
185                 malloc_trim(0);
186         }
187
188         return 0;
189 }
190
191 static void __appcore_timer_add(struct ui_priv *ui)
192 {
193         ui->mftimer = ecore_timer_add(5, __appcore_memory_flush_cb, ui);
194 }
195
196 static void __appcore_timer_del(struct ui_priv *ui)
197 {
198         if (ui->mftimer) {
199                 ecore_timer_del(ui->mftimer);
200                 ui->mftimer = NULL;
201         }
202 }
203
204 #else
205
206 static int __appcore_low_memory_post_cb(ui_priv *ui)
207 {
208         return -1;
209 }
210
211 #define __appcore_timer_add(ui) 0
212 #define __appcore_timer_del(ui) 0
213
214 #endif
215
216 static void __appcore_efl_memory_flush_cb(void)
217 {
218         _DBG("[APP %d]   __appcore_efl_memory_flush_cb()", _pid);
219         elm_cache_all_flush();
220 }
221 #ifdef WAYLAND
222 static void wl_raise_win()
223 {
224         Ecore_Wl_Window *win;
225         unsigned int win_id = appcore_get_main_window();
226         _DBG("Raise window : %d", win_id);
227         win = ecore_wl_window_find(win_id);
228         ecore_wl_window_activate(win);
229 }
230 #endif
231
232 static void __do_app(enum app_event event, void *data, bundle * b)
233 {
234         int r = -1;
235         struct ui_priv *ui = data;
236
237         _DBG("[APP %d] Event: %d", _pid, event);
238         _ret_if(ui == NULL || event >= AE_MAX);
239         _DBG("[APP %d] Event: %s State: %s", _pid, _ae_name[event],
240              _as_name[ui->state]);
241
242         if (event == AE_MEM_FLUSH) {
243                 ui->mfcb();
244                 return;
245         }
246
247         if (event == AE_LOWMEM_POST) {
248                 if (__appcore_low_memory_post_cb(ui) == 0)
249                         return;
250         }
251
252         if (!(ui->state == AS_PAUSED && event == AE_PAUSE))
253                 __appcore_timer_del(ui);
254
255         if (ui->state == AS_DYING) {
256                 _ERR("Skip the event in dying state");
257                 return;
258         }
259
260         if (event == AE_TERMINATE) {
261                 _DBG("[APP %d] TERMINATE", _pid);
262                 elm_exit();
263                 return;
264         }
265
266         if (event == AE_RAISE) {
267 #ifdef X11
268                 x_raise_win(getpid());
269 #else
270                 wl_raise_win();
271 #endif
272                 return;
273         }
274
275         if (event == AE_LOWER) {
276 #ifdef X11
277                 x_pause_win(getpid());
278                 return;
279 #endif
280                 /* TODO: wayland support */
281         }
282
283         _ret_if(ui->ops == NULL);
284
285         switch (event) {
286         case AE_RESET:
287                 _DBG("[APP %d] RESET", _pid);
288                 ui->pending_data = bundle_dup(b);
289                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]", ui->name);
290                 if (ui->ops->reset)
291                         r = ui->ops->reset(b, ui->ops->data);
292                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", ui->name);
293
294                 if (first_launch) {
295                         first_launch = FALSE;
296                 } else {
297                         _INFO("[APP %d] App already running, raise the window", _pid);
298 #ifdef X11
299                         x_raise_win(getpid());
300 #else
301                         wl_raise_win();
302 #endif
303                 }
304                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]",
305                     ui->name);
306                 break;
307         case AE_PAUSE:
308                 if (ui->state == AS_RUNNING) {
309                         _DBG("[APP %d] PAUSE", _pid);
310                         if (ui->ops->pause)
311                                 r = ui->ops->pause(ui->ops->data);
312                         ui->state = AS_PAUSED;
313                         if(r >= 0 && resource_reclaiming == TRUE)
314                                 __appcore_timer_add(ui);
315                 }
316                 /* TODO : rotation stop */
317                 //r = appcore_pause_rotation_cb();
318                 _send_to_resourced(PROC_STATUS_BACKGRD);
319                 break;
320         case AE_RESUME:
321                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]",
322                                 ui->name);
323                 if (ui->state == AS_PAUSED || ui->state == AS_CREATED) {
324                         _DBG("[APP %d] RESUME", _pid);
325
326                         if (ui->state == AS_CREATED) {
327                                 appcore_group_reset(ui->pending_data);
328                                 bundle_free(ui->pending_data);
329                                 ui->pending_data = NULL;
330                         } else {
331                                 appcore_group_resume();
332                         }
333
334                         if (ui->ops->resume) {
335                                 ui->ops->resume(ui->ops->data);
336                         }
337                         ui->state = AS_RUNNING;
338                 }
339                 /*TODO : rotation start*/
340                 //r = appcore_resume_rotation_cb();
341                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]",
342                     ui->name);
343                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]",
344                     ui->name);
345                 _send_to_resourced(PROC_STATUS_FOREGRD);
346                 break;
347         case AE_TERMINATE_BGAPP:
348                 if (ui->state == AS_PAUSED) {
349                         _DBG("[APP %d] is paused. TERMINATE", _pid);
350                         ui->state = AS_DYING;
351                         aul_status_update(STATUS_DYING);
352                         elm_exit();
353                 } else if (ui->state == AS_RUNNING) {
354                         _DBG("[APP %d] is running.", _pid);
355                 } else {
356                         _DBG("[APP %d] is another state", _pid);
357                 }
358                 break;
359         default:
360                 /* do nothing */
361                 break;
362         }
363 }
364
365 static struct ui_ops efl_ops = {
366         .data = &priv,
367         .cb_app = __do_app,
368 };
369
370
371 static bool __check_visible(void)
372 {
373         GSList *iter = NULL;
374         struct win_node *entry = NULL;
375
376         _DBG("[EVENT_TEST][EVENT] __check_visible\n");
377         
378         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
379                 entry = iter->data;     
380                 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
381                 if(entry->bfobscured == FALSE)
382                         return TRUE;            
383         }
384         return FALSE;
385 }
386
387 static GSList *__find_win(unsigned int win)
388 {
389         GSList *iter;
390         struct win_node *t;
391
392         for (iter = g_winnode_list; iter; iter = g_slist_next(iter)) {
393                 t = iter->data;
394                 if (t && t->win == win)
395                         return iter;
396         }
397
398         return NULL;
399 }
400
401 #ifdef X11
402 static bool __add_win(unsigned int win)
403 {
404         struct win_node *t;
405         GSList *f;
406
407         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
408
409         f = __find_win(win);
410         if (f) {
411                 errno = ENOENT;
412                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
413                 return FALSE;
414         }
415
416         t = calloc(1, sizeof(struct win_node));
417         if (t == NULL)
418                 return FALSE;
419
420         t->win = win;
421         t->bfobscured = FALSE;
422
423         g_winnode_list = g_slist_append(g_winnode_list, t);
424
425         return TRUE;
426 }
427 #else
428 static bool __add_win(unsigned int win, unsigned int surf)
429 {
430         struct win_node *t;
431         GSList *f;
432
433         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
434
435         f = __find_win(win);
436         if (f) {
437                 errno = ENOENT;
438                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
439                 return FALSE;
440         }
441
442         t = calloc(1, sizeof(struct win_node));
443         if (t == NULL)
444                 return FALSE;
445
446         t->win = win;
447         t->surf = surf;
448         t->bfobscured = FALSE;
449
450         g_winnode_list = g_slist_append(g_winnode_list, t);
451
452         return TRUE;
453 }
454 #endif
455
456 static bool __delete_win(unsigned int win)
457 {
458         GSList *f;
459
460         f = __find_win(win);
461         if (!f) {
462                 errno = ENOENT;
463                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
464                                 win);
465                 return FALSE;
466         }
467
468         free(f->data);
469         g_winnode_list = g_slist_delete_link(g_winnode_list, f);
470
471         return TRUE;
472 }
473
474 #ifdef X11
475 static bool __update_win(unsigned int win, bool bfobscured)
476 {
477         GSList *f;
478         struct win_node *t;
479
480         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
481              bfobscured);
482
483         f = __find_win(win);
484         if (!f) {
485                 errno = ENOENT;
486                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
487                 return FALSE;
488         }
489
490         g_winnode_list = g_slist_remove_link(g_winnode_list, f);
491
492         t = (struct win_node *)f->data;
493         t->win = win;
494         t->bfobscured = bfobscured;
495
496         g_winnode_list = g_slist_concat(g_winnode_list, f);
497
498         return TRUE;
499 }
500 #else
501 static bool __update_win(unsigned int win, unsigned int surf, bool bfobscured)
502 {
503         GSList *f;
504         struct win_node *t;
505
506         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
507              bfobscured);
508
509         f = __find_win(win);
510         if (!f) {
511                 errno = ENOENT;
512                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
513                 return FALSE;
514         }
515
516         g_winnode_list = g_slist_remove_link(g_winnode_list, f);
517
518         t = (struct win_node *)f->data;
519         t->win = win;
520         if (surf != 0)
521                 t->surf = surf;
522         t->bfobscured = bfobscured;
523
524         g_winnode_list = g_slist_concat(g_winnode_list, f);
525
526         return TRUE;
527 }
528 #endif
529
530 /* WM_ROTATE */
531 #ifdef X11
532 static Ecore_X_Atom _WM_WINDOW_ROTATION_SUPPORTED = 0;
533 static Ecore_X_Atom _WM_WINDOW_ROTATION_CHANGE_REQUEST = 0;
534
535 static int __check_wm_rotation_support(void)
536 {
537         _DBG("Disable window manager rotation");
538         return -1;
539
540         Ecore_X_Window root, win, win2;
541         int ret;
542
543         if (!_WM_WINDOW_ROTATION_SUPPORTED) {
544                 _WM_WINDOW_ROTATION_SUPPORTED =
545                                         ecore_x_atom_get("_E_WINDOW_ROTATION_SUPPORTED");
546         }
547
548         if (!_WM_WINDOW_ROTATION_CHANGE_REQUEST) {
549                 _WM_WINDOW_ROTATION_CHANGE_REQUEST =
550                                         ecore_x_atom_get("_E_WINDOW_ROTATION_CHANGE_REQUEST");
551         }
552
553         root = ecore_x_window_root_first_get();
554         ret = ecore_x_window_prop_xid_get(root,
555                         _WM_WINDOW_ROTATION_SUPPORTED,
556                         ECORE_X_ATOM_WINDOW,
557                         &win, 1);
558         if ((ret == 1) && (win))
559         {
560                 ret = ecore_x_window_prop_xid_get(win,
561                                 _WM_WINDOW_ROTATION_SUPPORTED,
562                                 ECORE_X_ATOM_WINDOW,
563                                 &win2, 1);
564                 if ((ret == 1) && (win2 == win))
565                         return 0;
566         }
567
568         return -1;
569 }
570
571 static void __set_wm_rotation_support(unsigned int win, unsigned int set)
572 {
573         GSList *iter = NULL;
574         struct win_node *entry = NULL;
575
576         if (0 == win) {
577                 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
578                         entry = iter->data;
579                         if (entry->win) {
580                                 ecore_x_window_prop_card32_set(entry->win,
581                                                 _WM_WINDOW_ROTATION_SUPPORTED,
582                                                 &set, 1);
583                         }
584                 }
585         } else {
586                 ecore_x_window_prop_card32_set(win,
587                                 _WM_WINDOW_ROTATION_SUPPORTED,
588                                 &set, 1);
589         }
590 }
591
592 #endif
593
594 static Eina_Bool __show_cb(void *data, int type, void *event)
595 {
596 #ifdef WAYLAND
597         Ecore_Wl_Event_Window_Show *ev;
598
599         ev = event;
600         if (ev->parent_win != 0)
601         {
602                 // This is child window. Skip!!!
603                 return ECORE_CALLBACK_PASS_ON;
604         }
605
606         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x, %d\n", ev->win, ev->data[0]);
607
608         if (!__find_win((unsigned int)ev->win))
609                 __add_win((unsigned int)ev->win, (unsigned int)ev->data[0]);
610         else
611                 __update_win((unsigned int)ev->win, (unsigned int)ev->data[0], FALSE);
612
613 #else
614         Ecore_X_Event_Window_Show *ev;
615         int ret;
616         Ecore_X_Window parent;
617
618         ev = event;
619
620         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x\n", ev->win);
621
622         if (!__find_win((unsigned int)ev->win)) {
623                 /* WM_ROTATE */
624                 if ((priv.wm_rot_supported) && (1 == priv.rot_started)) {
625                         __set_wm_rotation_support(ev->win, 1);
626                 }
627                 __add_win((unsigned int)ev->win);
628         }
629         else
630                 __update_win((unsigned int)ev->win, FALSE);
631 #endif
632
633         return ECORE_CALLBACK_RENEW;
634 }
635
636 static Eina_Bool __hide_cb(void *data, int type, void *event)
637 {
638 #ifdef WAYLAND
639         Ecore_Wl_Event_Window_Hide *ev;
640 #else
641         Ecore_X_Event_Window_Hide *ev;
642 #endif
643         int bvisibility = 0;
644
645         ev = event;
646
647         _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
648
649         if (__find_win((unsigned int)ev->win)) {
650                 __delete_win((unsigned int)ev->win);
651                 bvisibility = __check_visible();
652                 if (!bvisibility && b_active == TRUE) {
653                         _DBG(" Go to Pasue state \n");
654                         b_active = FALSE;
655                         __do_app(AE_PAUSE, data, NULL);
656                 }
657         }
658
659         return ECORE_CALLBACK_RENEW;
660 }
661
662 static Eina_Bool __visibility_cb(void *data, int type, void *event)
663 {
664 #ifdef WAYLAND
665         Ecore_Wl_Event_Window_Visibility_Change *ev;
666         int bvisibility = 0;
667         ev = event;
668         __update_win((unsigned int)ev->win, 0, ev->fully_obscured);
669 #else
670         Ecore_X_Event_Window_Visibility_Change *ev;
671         int bvisibility = 0;
672
673         ev = event;
674
675         __update_win((unsigned int)ev->win, ev->fully_obscured);
676 #endif
677         bvisibility = __check_visible();
678
679         _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
680
681         if (bvisibility && b_active == FALSE) {
682                 _DBG(" Go to Resume state\n");
683                 b_active = TRUE;
684                 __do_app(AE_RESUME, data, NULL);
685
686         } else if (!bvisibility && b_active == TRUE) {
687                 _DBG(" Go to Pasue state \n");
688                 b_active = FALSE;
689                 __do_app(AE_PAUSE, data, NULL);
690         } else
691                 _DBG(" No change state \n");
692
693         return ECORE_CALLBACK_RENEW;
694
695 }
696
697 #ifdef X11
698 /* WM_ROTATE */
699 static Eina_Bool __cmsg_cb(void *data, int type, void *event)
700 {
701         struct ui_priv *ui = (struct ui_priv *)data;
702         Ecore_X_Event_Client_Message *e = event;
703
704         if (!ui) return ECORE_CALLBACK_PASS_ON;
705         if (e->format != 32) return ECORE_CALLBACK_PASS_ON;
706         if (e->message_type == _WM_WINDOW_ROTATION_CHANGE_REQUEST) {
707                 if ((0 == ui->wm_rot_supported) ||
708                         (0 == ui->rot_started) ||
709                         (NULL == ui->rot_cb)) {
710                         return ECORE_CALLBACK_PASS_ON;
711                 }
712
713                 enum appcore_rm rm;
714                 switch (e->data.l[1])
715                 {
716                         case   0: rm = APPCORE_RM_PORTRAIT_NORMAL;   break;
717                         case  90: rm = APPCORE_RM_LANDSCAPE_REVERSE; break;
718                         case 180: rm = APPCORE_RM_PORTRAIT_REVERSE;  break;
719                         case 270: rm = APPCORE_RM_LANDSCAPE_NORMAL;  break;
720                         default:  rm = APPCORE_RM_UNKNOWN;           break;
721                 }
722
723                 ui->rot_mode = rm;
724
725                 if (APPCORE_RM_UNKNOWN != rm) {
726                         ui->rot_cb((void *)&rm, rm, ui->rot_cb_data);
727                 }
728         }
729
730         return ECORE_CALLBACK_PASS_ON;
731 }
732 #endif
733
734 static void __add_climsg_cb(struct ui_priv *ui)
735 {
736         _ret_if(ui == NULL);
737 #ifdef WAYLAND
738         ui->hshow =
739             ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_SHOW, __show_cb, ui);
740         ui->hhide =
741             ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_HIDE, __hide_cb, ui);
742         ui->hvchange =
743             ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
744                                     __visibility_cb, ui);
745 #else
746         ui->hshow =
747             ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, __show_cb, ui);
748         ui->hhide =
749             ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, __hide_cb, ui);
750         ui->hvchange =
751             ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE,
752                                     __visibility_cb, ui);
753
754         /* Add client message callback for WM_ROTATE */
755         if(!__check_wm_rotation_support())
756         {
757                 ui->hcmsg =
758                         ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, __cmsg_cb, ui);
759                 ui->wm_rot_supported = 1;
760                 appcore_set_wm_rotation(&wm_rotate);
761         }
762 #endif
763 }
764
765 static int __before_loop(struct ui_priv *ui, int *argc, char ***argv)
766 {
767         int r;
768         char *hwacc = NULL;
769
770         if (argc == NULL || argv == NULL) {
771                 _ERR("argc/argv is NULL");
772                 errno = EINVAL;
773                 return -1;
774         }
775
776         g_type_init();
777         elm_init(*argc, *argv);
778
779         hwacc = getenv("HWACC");
780
781         if(hwacc == NULL) {
782                 _DBG("elm_config_preferred_engine_set is not called");
783         } else if(strcmp(hwacc, "USE") == 0) {
784 #ifdef WAYLAND
785                 elm_config_preferred_engine_set("wayland_egl");
786                 _DBG("elm_config_preferred_engine_set : wayland_egl");
787 #else
788                 elm_config_preferred_engine_set("opengl_x11");
789                 _DBG("elm_config_preferred_engine_set : opengl_x11");
790 #endif
791         } else if(strcmp(hwacc, "NOT_USE") == 0) {
792 #ifdef WAYLAND
793                 elm_config_preferred_engine_set("wayland_shm");
794                 _DBG("elm_config_preferred_engine_set : wayland_shm");
795 #else
796                 elm_config_preferred_engine_set("software_x11");
797                 _DBG("elm_config_preferred_engine_set : software_x11");
798 #endif
799         } else {
800                 _DBG("elm_config_preferred_engine_set is not called");
801         }
802
803         r = appcore_init(ui->name, &efl_ops, *argc, *argv);
804         _retv_if(r == -1, -1);
805
806         LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:appcore_init:done]", ui->name);
807         if (ui->ops && ui->ops->create) {
808                 r = ui->ops->create(ui->ops->data);
809                 if (r < 0) {
810                         _ERR("create() return error");
811                         appcore_exit();
812                         if (ui->ops && ui->ops->terminate)
813                                 ui->ops->terminate(ui->ops->data);
814                         errno = ECANCELED;
815                         return -1;
816                 }
817                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]",
818                     ui->name);
819         }
820         ui->state = AS_CREATED;
821
822         __add_climsg_cb(ui);
823
824         return 0;
825 }
826
827 static void __after_loop(struct ui_priv *ui)
828 {
829         appcore_unset_rotation_cb();
830         appcore_exit();
831
832         if (ui->state == AS_RUNNING) {
833                 _DBG("[APP %d] PAUSE before termination", _pid);
834                 if (ui->ops && ui->ops->pause)
835                         ui->ops->pause(ui->ops->data);
836         }
837
838         if (ui->ops && ui->ops->terminate)
839                 ui->ops->terminate(ui->ops->data);
840
841         ui->state = AS_DYING;
842
843         if (ui->hshow)
844                 ecore_event_handler_del(ui->hshow);
845         if (ui->hhide)
846                 ecore_event_handler_del(ui->hhide);
847         if (ui->hvchange)
848                 ecore_event_handler_del(ui->hvchange);
849
850         __appcore_timer_del(ui);
851
852         elm_shutdown();
853 }
854
855 static int __set_data(struct ui_priv *ui, const char *name,
856                     struct appcore_ops *ops)
857 {
858         if (ui->name) {
859                 _ERR("Mainloop already started");
860                 errno = EINPROGRESS;
861                 return -1;
862         }
863
864         if (name == NULL || name[0] == '\0') {
865                 _ERR("Invalid name");
866                 errno = EINVAL;
867                 return -1;
868         }
869
870         if (ops == NULL) {
871                 _ERR("ops is NULL");
872                 errno = EINVAL;
873                 return -1;
874         }
875
876         ui->name = strdup(name);
877         _retv_if(ui->name == NULL, -1);
878
879         ui->ops = ops;
880
881         ui->mfcb = __appcore_efl_memory_flush_cb;
882
883         _pid = getpid();
884
885         /* WM_ROTATE */
886         ui->wm_rot_supported = 0;
887         ui->rot_started = 0;
888         ui->rot_cb = NULL;
889         ui->rot_cb_data = NULL;
890         ui->rot_mode = APPCORE_RM_UNKNOWN;
891
892         return 0;
893 }
894
895 static void __unset_data(struct ui_priv *ui)
896 {
897         if (ui->name)
898                 free((void *)ui->name);
899
900         memset(ui, 0, sizeof(struct ui_priv));
901 }
902
903 /* WM_ROTATE */
904 static int __wm_set_rotation_cb(int (*cb) (void *event_info, enum appcore_rm, void *), void *data)
905 {
906         if (cb == NULL) {
907                 errno = EINVAL;
908                 return -1;
909         }
910
911         if ((priv.wm_rot_supported) && (0 == priv.rot_started)) {
912                 __set_wm_rotation_support(0, 1);
913         }
914
915         priv.rot_cb = cb;
916         priv.rot_cb_data = data;
917         priv.rot_started = 1;
918
919         return 0;
920 }
921
922 static int __wm_unset_rotation_cb(void)
923 {
924         if ((priv.wm_rot_supported) && (1 == priv.rot_started)) {
925                 __set_wm_rotation_support(0, 0);
926         }
927
928         priv.rot_cb = NULL;
929         priv.rot_cb_data = NULL;
930         priv.rot_started = 0;
931
932         return 0;
933 }
934
935 static int __wm_get_rotation_state(enum appcore_rm *curr)
936 {
937         if (curr == NULL) {
938                 errno = EINVAL;
939                 return -1;
940         }
941
942         *curr = priv.rot_mode;
943
944         return 0;
945 }
946
947 static int __wm_pause_rotation_cb(void)
948 {
949         if ((1 == priv.rot_started) && (priv.wm_rot_supported)) {
950                 __set_wm_rotation_support(0, 0);
951         }
952
953         priv.rot_started = 0;
954
955         return 0;
956 }
957
958 static int __wm_resume_rotation_cb(void)
959 {
960         if ((0 == priv.rot_started) && (priv.wm_rot_supported)) {
961                 __set_wm_rotation_support(0, 1);
962         }
963
964         priv.rot_started = 1;
965
966         return 0;
967 }
968
969 static struct ui_wm_rotate wm_rotate = {
970         __wm_set_rotation_cb,
971         __wm_unset_rotation_cb,
972         __wm_get_rotation_state,
973         __wm_pause_rotation_cb,
974         __wm_resume_rotation_cb
975 };
976
977 EXPORT_API int appcore_efl_main(const char *name, int *argc, char ***argv,
978                                 struct appcore_ops *ops)
979 {
980         int r;
981
982         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", name);
983
984         r = __set_data(&priv, name, ops);
985         _retv_if(r == -1, -1);
986
987         r = __before_loop(&priv, argc, argv);
988         if (r == -1) {
989                 __unset_data(&priv);
990                 return -1;
991         }
992
993         elm_run();
994
995         aul_status_update(STATUS_DYING);
996
997         __after_loop(&priv);
998
999         __unset_data(&priv);
1000
1001         return 0;
1002 }
1003
1004 EXPORT_API int appcore_set_system_resource_reclaiming(bool enable)
1005 {
1006         resource_reclaiming = enable;
1007
1008         return 0;
1009 }
1010
1011 EXPORT_API int appcore_set_app_state(int state)
1012 {
1013         priv.state = state;
1014
1015         tmp_val = 1;
1016
1017         return 0;
1018 }
1019
1020 EXPORT_API unsigned int appcore_get_main_window()
1021 {
1022         struct win_node *entry = NULL;
1023
1024         if (g_winnode_list != NULL) {
1025                 entry = g_winnode_list->data;
1026                 return (unsigned int) entry->win;
1027         }
1028         return 0;
1029 }
1030 #ifdef WAYLAND
1031 EXPORT_API unsigned int appcore_get_main_surface()
1032 {
1033         struct win_node *entry = NULL;
1034
1035         if (g_winnode_list != NULL) {
1036                 entry = g_winnode_list->data;
1037                 return (unsigned int) entry->surf;
1038         }
1039         return 0;
1040 }
1041 #endif