Merge branch tizen_2.2 into tizen
[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 #ifndef WAYLAND
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 <stdbool.h>
46 #include <aul.h>
47 #include "appcore-internal.h"
48 #include "appcore-efl.h"
49
50 #define SYSMAN_MAXSTR 100
51 #define SYSMAN_MAXARG 16
52 #define SYSNOTI_SOCKET_PATH "/tmp/sn"
53 #define RETRY_READ_COUNT        10
54
55 #define PREDEF_BACKGRD                          "backgrd"
56 #define PREDEF_FOREGRD                          "foregrd"
57
58 enum sysnoti_cmd {
59         ADD_SYSMAN_ACTION,
60         CALL_SYSMAN_ACTION
61 };
62
63 struct sysnoti {
64         int pid;
65         int cmd;
66         char *type;
67         char *path;
68         int argc;
69         char *argv[SYSMAN_MAXARG];
70 };
71
72 static pid_t _pid;
73
74 static bool resource_reclaiming = TRUE;
75 static int tmp_val = 0;
76
77
78 struct ui_priv {
79         const char *name;
80         enum app_state state;
81
82         Ecore_Event_Handler *hshow;
83         Ecore_Event_Handler *hhide;
84         Ecore_Event_Handler *hvchange;
85         Ecore_Event_Handler *hcmsg; /* WM_ROTATE */
86
87         Ecore_Timer *mftimer;   /* Ecore Timer for memory flushing */
88
89         struct appcore_ops *ops;
90         void (*mfcb) (void);    /* Memory Flushing Callback */
91
92         /* WM_ROTATE */
93         int wm_rot_supported;
94         int rot_started;
95         int (*rot_cb) (enum appcore_rm, void *);
96         void *rot_cb_data;
97         enum appcore_rm rot_mode;
98 };
99
100 static struct ui_priv priv;
101
102 static const char *_ae_name[AE_MAX] = {
103         [AE_UNKNOWN] = "UNKNOWN",
104         [AE_CREATE] = "CREATE",
105         [AE_TERMINATE] = "TERMINATE",
106         [AE_PAUSE] = "PAUSE",
107         [AE_RESUME] = "RESUME",
108         [AE_RESET] = "RESET",
109         [AE_LOWMEM_POST] = "LOWMEM_POST",
110         [AE_MEM_FLUSH] = "MEM_FLUSH",
111 };
112
113 static const char *_as_name[] = {
114         [AS_NONE] = "NONE",
115         [AS_CREATED] = "CREATED",
116         [AS_RUNNING] = "RUNNING",
117         [AS_PAUSED] = "PAUSED",
118         [AS_DYING] = "DYING",
119 };
120
121 static bool b_active = 0;
122 struct win_node {
123         unsigned int win;
124         bool bfobscured;
125 };
126
127 static struct ui_wm_rotate wm_rotate;
128
129 static inline int send_int(int fd, int val)
130 {
131         return write(fd, &val, sizeof(int));
132 }
133
134 static inline int send_str(int fd, char *str)
135 {
136         int len;
137         int ret;
138         if (str == NULL) {
139                 len = 0;
140                 ret = write(fd, &len, sizeof(int));
141         } else {
142                 len = strlen(str);
143                 if (len > SYSMAN_MAXSTR)
144                         len = SYSMAN_MAXSTR;
145                 write(fd, &len, sizeof(int));
146                 ret = write(fd, str, len);
147         }
148         return ret;
149 }
150
151 static int sysnoti_send(struct sysnoti *msg)
152 {
153         _ERR("--- %s: start", __FUNCTION__);
154         int client_len;
155         int client_sockfd;
156         int result;
157         int r;
158         int retry_count = 0;
159         struct sockaddr_un clientaddr;
160         int i;
161
162         client_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
163         if (client_sockfd == -1) {
164                 _ERR("%s: socket create failed\n", __FUNCTION__);
165                 return -1;
166         }
167         bzero(&clientaddr, sizeof(clientaddr));
168         clientaddr.sun_family = AF_UNIX;
169         strncpy(clientaddr.sun_path, SYSNOTI_SOCKET_PATH, sizeof(clientaddr.sun_path) - 1);
170         client_len = sizeof(clientaddr);
171
172         if (connect(client_sockfd, (struct sockaddr *)&clientaddr, client_len) <
173             0) {
174                 _ERR("%s: connect failed\n", __FUNCTION__);
175                 close(client_sockfd);
176                 return -1;
177         }
178
179         send_int(client_sockfd, msg->pid);
180         send_int(client_sockfd, msg->cmd);
181         send_str(client_sockfd, msg->type);
182         send_str(client_sockfd, msg->path);
183         send_int(client_sockfd, msg->argc);
184         for (i = 0; i < msg->argc; i++)
185                 send_str(client_sockfd, msg->argv[i]);
186
187         _ERR("--- %s: read", __FUNCTION__);
188         while (retry_count < RETRY_READ_COUNT) {
189                 r = read(client_sockfd, &result, sizeof(int));
190                 if (r < 0) {
191                         if (errno == EINTR) {
192                                 _ERR("Re-read for error(EINTR)");
193                                 retry_count++;
194                                 continue;
195                         }
196                         _ERR("Read fail for str length");
197                         result = -1;
198                         break;
199
200                 }
201                 break;
202         }
203         if (retry_count == RETRY_READ_COUNT) {
204                 _ERR("Read retry failed");
205         }
206
207         close(client_sockfd);
208         _ERR("--- %s: end", __FUNCTION__);
209         return result;
210 }
211
212 static int _call_predef_action(const char *type, int num, ...)
213 {
214         _ERR("--- %s: start", __FUNCTION__);
215         struct sysnoti *msg;
216         int ret;
217         va_list argptr;
218
219         int i;
220         char *args = NULL;
221
222         if (type == NULL || num > SYSMAN_MAXARG) {
223                 errno = EINVAL;
224                 return -1;
225         }
226
227         msg = malloc(sizeof(struct sysnoti));
228
229         if (msg == NULL) {
230                 /* Do something for not enought memory error */
231                 return -1;
232         }
233
234         msg->pid = getpid();
235         msg->cmd = CALL_SYSMAN_ACTION;
236         msg->type = (char *)type;
237         msg->path = NULL;
238
239         msg->argc = num;
240         va_start(argptr, num);
241         for (i = 0; i < num; i++) {
242                 args = va_arg(argptr, char *);
243                 msg->argv[i] = args;
244         }
245         va_end(argptr);
246
247         _ERR("--- %s: send msg", __FUNCTION__);
248         ret = sysnoti_send(msg);
249         free(msg);
250
251         _ERR("--- %s: end", __FUNCTION__);
252         return ret;
253 }
254
255 static int _inform_foregrd(void)
256 {
257         char buf[255];
258         snprintf(buf, sizeof(buf), "%d", getpid());
259         return _call_predef_action(PREDEF_FOREGRD, 1, buf);
260 }
261
262 static int _inform_backgrd(void)
263 {
264         char buf[255];
265         snprintf(buf, sizeof(buf), "%d", getpid());
266         return _call_predef_action(PREDEF_BACKGRD, 1, buf);
267 }
268
269
270 static int WIN_COMP(gconstpointer data1, gconstpointer data2)
271 {
272         struct win_node *a = (struct win_node *)data1;
273         struct win_node *b = (struct win_node *)data2;
274         return (int)((a->win)-(b->win));
275 }
276
277 GSList *g_winnode_list = NULL;
278
279 #if defined(MEMORY_FLUSH_ACTIVATE)
280 static Eina_Bool __appcore_memory_flush_cb(void *data)
281 {
282         struct ui_priv *ui = (struct ui_priv *)data;
283
284         appcore_flush_memory();
285         ui->mftimer = NULL;
286
287         return ECORE_CALLBACK_CANCEL;
288 }
289
290 static int __appcore_low_memory_post_cb(struct ui_priv *ui)
291 {
292         if (ui->state == AS_PAUSED) {
293                 appcore_flush_memory();
294         } else {
295                 malloc_trim(0);
296         }
297
298         return 0;
299 }
300
301 static void __appcore_timer_add(struct ui_priv *ui)
302 {
303         ui->mftimer = ecore_timer_add(5, __appcore_memory_flush_cb, ui);
304 }
305
306 static void __appcore_timer_del(struct ui_priv *ui)
307 {
308         if (ui->mftimer) {
309                 ecore_timer_del(ui->mftimer);
310                 ui->mftimer = NULL;
311         }
312 }
313
314 #else
315
316 static int __appcore_low_memory_post_cb(ui_priv *ui)
317 {
318         return -1;
319 }
320
321 #define __appcore_timer_add(ui) 0
322 #define __appcore_timer_del(ui) 0
323
324 #endif
325
326 static void __appcore_efl_memory_flush_cb(void)
327 {
328         _DBG("[APP %d]   __appcore_efl_memory_flush_cb()", _pid);
329         elm_cache_all_flush();
330 }
331
332 static void __do_app(enum app_event event, void *data, bundle * b)
333 {
334         int r = -1;
335         struct ui_priv *ui = data;
336
337         _DBG("[APP %d] Event: %d", _pid, event);
338         _ret_if(ui == NULL || event >= AE_MAX);
339         _DBG("[APP %d] Event: %s State: %s", _pid, _ae_name[event],
340              _as_name[ui->state]);
341
342         if (event == AE_MEM_FLUSH) {
343                 ui->mfcb();
344                 return;
345         }
346
347         if (event == AE_LOWMEM_POST) {
348                 if (__appcore_low_memory_post_cb(ui) == 0)
349                         return;
350         }
351
352         if (!(ui->state == AS_PAUSED && event == AE_PAUSE))
353                 __appcore_timer_del(ui);
354
355         if (event == AE_TERMINATE) {
356                 _DBG("[APP %d] TERMINATE", _pid);
357                 ui->state = AS_DYING;
358                 elm_exit();
359                 return;
360         }
361
362         _ret_if(ui->ops == NULL);
363
364         switch (event) {
365         case AE_RESET:
366                 _DBG("[APP %d] RESET", _pid);
367                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]",
368                     ui->name);
369                 if (ui->ops->reset)
370                         r = ui->ops->reset(b, ui->ops->data);
371                 ui->state = AS_RUNNING;
372                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]",
373                     ui->name);
374                 break;
375         case AE_PAUSE:
376                 if (ui->state == AS_RUNNING) {
377                         _DBG("[APP %d] PAUSE", _pid);
378                         if (ui->ops->pause)
379                                 r = ui->ops->pause(ui->ops->data);
380                         ui->state = AS_PAUSED;
381                         if(r >= 0 && resource_reclaiming == TRUE)
382                                 __appcore_timer_add(ui);
383                 }
384                 /* TODO : rotation stop */
385                 //r = appcore_pause_rotation_cb();
386
387                 _inform_backgrd();
388                 break;
389         case AE_RESUME:
390                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]",
391                     ui->name);
392                 if (ui->state == AS_PAUSED || tmp_val == 1) {
393                         _DBG("[APP %d] RESUME", _pid);
394                         if (ui->ops->resume)
395                                 r = ui->ops->resume(ui->ops->data);
396                         ui->state = AS_RUNNING;
397                          tmp_val = 0;
398                 }
399                 /*TODO : rotation start*/
400                 //r = appcore_resume_rotation_cb();
401                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]",
402                     ui->name);
403                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]",
404                     ui->name);
405                 _inform_foregrd();
406
407                 break;
408         default:
409                 /* do nothing */
410                 break;
411         }
412 }
413
414 static struct ui_ops efl_ops = {
415         .data = &priv,
416         .cb_app = __do_app,
417 };
418
419
420 static bool __check_visible(void)
421 {
422         GSList *iter = NULL;
423         struct win_node *entry = NULL;
424
425         _DBG("[EVENT_TEST][EVENT] __check_visible\n");
426         
427         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
428                 entry = iter->data;     
429                 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
430                 if(entry->bfobscured == FALSE)
431                         return TRUE;            
432         }
433         return FALSE;
434 }
435
436 static bool __exist_win(unsigned int win)
437 {
438         struct win_node temp;
439         GSList *f;
440
441         temp.win = win;
442
443         f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
444         if (f == NULL) {
445                 return FALSE;
446         } else {
447                 return TRUE;
448         }
449
450 }
451
452 static bool __add_win(unsigned int win)
453 {
454         struct win_node *t;
455         GSList *f;
456
457         t = calloc(1, sizeof(struct win_node));
458         if (t == NULL)
459                 return FALSE;
460
461         t->win = win;
462         t->bfobscured = FALSE;
463
464         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
465
466         f = g_slist_find_custom(g_winnode_list, t, WIN_COMP);
467
468         if (f) {
469                 errno = ENOENT;
470                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
471                 free(t);
472                 return 0;
473         }
474
475         g_winnode_list = g_slist_append(g_winnode_list, t);
476
477         return TRUE;
478
479 }
480
481 static bool __delete_win(unsigned int win)
482 {
483         struct win_node temp;
484         GSList *f;
485
486         temp.win = win;
487
488         f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
489         if (f == NULL) {
490                 errno = ENOENT;
491                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
492                      win);
493                 return 0;
494         }
495
496         g_winnode_list = g_slist_remove_link(g_winnode_list, f);
497
498         free(f->data);
499
500         return TRUE;
501 }
502
503 static bool __update_win(unsigned int win, bool bfobscured)
504 {
505         struct win_node temp;
506         GSList *f;
507
508         struct win_node *t;
509
510         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
511              bfobscured);
512
513         temp.win = win;
514
515         f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
516
517         if (f == NULL) {
518                 errno = ENOENT;
519                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
520                 return FALSE;
521         }
522
523         g_winnode_list = g_slist_remove_link(g_winnode_list, f);
524
525         free(f->data);
526
527         t = calloc(1, sizeof(struct win_node));
528         if (t == NULL)
529                 return FALSE;
530
531         t->win = win;
532         t->bfobscured = bfobscured;
533
534         g_winnode_list = g_slist_append(g_winnode_list, t);
535         
536         return TRUE;
537
538 }
539
540 /* WM_ROTATE */
541 #ifndef WAYLAND
542 static Ecore_X_Atom _WM_WINDOW_ROTATION_SUPPORTED = 0;
543 static Ecore_X_Atom _WM_WINDOW_ROTATION_CHANGE_REQUEST = 0;
544
545 static int __check_wm_rotation_support(void)
546 {
547         _DBG("Disable window manager rotation");
548         return -1;
549
550         Ecore_X_Window root, win, win2;
551         int ret;
552
553         if (!_WM_WINDOW_ROTATION_SUPPORTED) {
554                 _WM_WINDOW_ROTATION_SUPPORTED =
555                                         ecore_x_atom_get("_E_WINDOW_ROTATION_SUPPORTED");
556         }
557
558         if (!_WM_WINDOW_ROTATION_CHANGE_REQUEST) {
559                 _WM_WINDOW_ROTATION_CHANGE_REQUEST =
560                                         ecore_x_atom_get("_E_WINDOW_ROTATION_CHANGE_REQUEST");
561         }
562
563         root = ecore_x_window_root_first_get();
564         ret = ecore_x_window_prop_xid_get(root,
565                         _WM_WINDOW_ROTATION_SUPPORTED,
566                         ECORE_X_ATOM_WINDOW,
567                         &win, 1);
568         if ((ret == 1) && (win))
569         {
570                 ret = ecore_x_window_prop_xid_get(win,
571                                 _WM_WINDOW_ROTATION_SUPPORTED,
572                                 ECORE_X_ATOM_WINDOW,
573                                 &win2, 1);
574                 if ((ret == 1) && (win2 == win))
575                         return 0;
576         }
577
578         return -1;
579 }
580
581 static void __set_wm_rotation_support(unsigned int win, unsigned int set)
582 {
583         GSList *iter = NULL;
584         struct win_node *entry = NULL;
585
586         if (0 == win) {
587                 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
588                         entry = iter->data;
589                         if (entry->win) {
590                                 ecore_x_window_prop_card32_set(entry->win,
591                                                 _WM_WINDOW_ROTATION_SUPPORTED,
592                                                 &set, 1);
593                         }
594                 }
595         } else {
596                 ecore_x_window_prop_card32_set(win,
597                                 _WM_WINDOW_ROTATION_SUPPORTED,
598                                 &set, 1);
599         }
600 }
601
602 Ecore_X_Atom atom_parent;
603 #endif
604
605 static Eina_Bool __show_cb(void *data, int type, void *event)
606 {
607 #ifndef WAYLAND
608         Ecore_X_Event_Window_Show *ev;
609         int ret;
610         Ecore_X_Window parent;
611
612         ev = event;
613
614         ret = ecore_x_window_prop_window_get(ev->win, atom_parent, &parent, 1);
615         if (ret != 1)
616         {
617                 // This is child window. Skip!!!
618                 return ECORE_CALLBACK_PASS_ON;
619         }
620
621         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x\n", ev->win);
622
623         if (!__exist_win((unsigned int)ev->win)) {
624                 /* WM_ROTATE */
625                 if ((priv.wm_rot_supported) && (1 == priv.rot_started)) {
626                         __set_wm_rotation_support(ev->win, 1);
627                 }
628                 __add_win((unsigned int)ev->win);
629         }
630         else
631                 __update_win((unsigned int)ev->win, FALSE);
632 #endif
633
634         return ECORE_CALLBACK_RENEW;
635 }
636
637 static Eina_Bool __hide_cb(void *data, int type, void *event)
638 {
639 #ifndef WAYLAND
640         Ecore_X_Event_Window_Hide *ev;
641         int bvisibility = 0;
642
643         ev = event;
644
645         _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
646
647         if (__exist_win((unsigned int)ev->win)) {
648                 __delete_win((unsigned int)ev->win);
649                 
650                 bvisibility = __check_visible();
651                 if (!bvisibility && b_active == 1) {
652                         _DBG(" Go to Pasue state \n");
653                         b_active = 0;
654                         __do_app(AE_PAUSE, data, NULL);
655                 }
656         }
657 #endif
658
659         return ECORE_CALLBACK_RENEW;
660 }
661
662 static Eina_Bool __visibility_cb(void *data, int type, void *event)
663 {
664 #ifndef WAYLAND
665         Ecore_X_Event_Window_Visibility_Change *ev;
666         int bvisibility = 0;
667
668         ev = event;
669
670         __update_win((unsigned int)ev->win, ev->fully_obscured);
671         bvisibility = __check_visible();
672
673         if (bvisibility && b_active == 0) {
674                 _DBG(" Go to Resume state\n");
675                 b_active = 1;
676                 __do_app(AE_RESUME, data, NULL);
677
678         } else if (!bvisibility && b_active == 1) {
679                 _DBG(" Go to Pasue state \n");
680                 b_active = 0;
681                 __do_app(AE_PAUSE, data, NULL);
682         } else
683                 _DBG(" No change state \n");
684 #endif
685
686         return ECORE_CALLBACK_RENEW;
687
688 }
689
690 #ifndef WAYLAND
691 /* WM_ROTATE */
692 static Eina_Bool __cmsg_cb(void *data, int type, void *event)
693 {
694         struct ui_priv *ui = (struct ui_priv *)data;
695         Ecore_X_Event_Client_Message *e = event;
696
697         if (!ui) return ECORE_CALLBACK_PASS_ON;
698         if (e->format != 32) return ECORE_CALLBACK_PASS_ON;
699         if (e->message_type == _WM_WINDOW_ROTATION_CHANGE_REQUEST) {
700                 if ((0 == ui->wm_rot_supported) ||
701                         (0 == ui->rot_started) ||
702                         (NULL == ui->rot_cb)) {
703                         return ECORE_CALLBACK_PASS_ON;
704                 }
705
706                 enum appcore_rm rm;
707                 switch (e->data.l[1])
708                 {
709                         case   0: rm = APPCORE_RM_PORTRAIT_NORMAL;   break;
710                         case  90: rm = APPCORE_RM_LANDSCAPE_REVERSE; break;
711                         case 180: rm = APPCORE_RM_PORTRAIT_REVERSE;  break;
712                         case 270: rm = APPCORE_RM_LANDSCAPE_NORMAL;  break;
713                         default:  rm = APPCORE_RM_UNKNOWN;           break;
714                 }
715
716                 ui->rot_mode = rm;
717
718                 if (APPCORE_RM_UNKNOWN != rm) {
719                         ui->rot_cb(rm, ui->rot_cb_data);
720                 }
721         }
722
723         return ECORE_CALLBACK_PASS_ON;
724 }
725 #endif
726
727 static void __add_climsg_cb(struct ui_priv *ui)
728 {
729         _ret_if(ui == NULL);
730 #ifndef WAYLAND
731         atom_parent = ecore_x_atom_get("_E_PARENT_BORDER_WINDOW");
732         if (!atom_parent)
733         {
734                 // Do Error Handling
735         }
736
737         ui->hshow =
738             ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, __show_cb, ui);
739         ui->hhide =
740             ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, __hide_cb, ui);
741         ui->hvchange =
742             ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE,
743                                     __visibility_cb, ui);
744
745         /* Add client message callback for WM_ROTATE */
746         if(!__check_wm_rotation_support())
747         {
748                 ui->hcmsg =
749                         ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, __cmsg_cb, ui);
750                 ui->wm_rot_supported = 1;
751                 appcore_set_wm_rotation(&wm_rotate);
752         }
753 #endif
754 }
755
756 static int __before_loop(struct ui_priv *ui, int *argc, char ***argv)
757 {
758         int r;
759         char *hwacc = NULL;
760
761         if (argc == NULL || argv == NULL) {
762                 _ERR("argc/argv is NULL");
763                 errno = EINVAL;
764                 return -1;
765         }
766
767         g_type_init();
768         elm_init(*argc, *argv);
769
770         hwacc = getenv("HWACC");
771
772         if(hwacc == NULL) {
773                 _DBG("elm_config_preferred_engine_set is not called");
774         } else if(strcmp(hwacc, "USE") == 0) {
775 #ifdef WAYLAND
776                 elm_config_preferred_engine_set("wayland_egl");
777                 _DBG("elm_config_preferred_engine_set : wayland_egl");
778 #else
779                 elm_config_preferred_engine_set("opengl_x11");
780                 _DBG("elm_config_preferred_engine_set : opengl_x11");
781 #endif
782         } else if(strcmp(hwacc, "NOT_USE") == 0) {
783 #ifdef WAYLAND
784                 elm_config_preferred_engine_set("wayland_shm");
785                 _DBG("elm_config_preferred_engine_set : wayland_shm");
786 #else
787                 elm_config_preferred_engine_set("software_x11");
788                 _DBG("elm_config_preferred_engine_set : software_x11");
789 #endif
790         } else {
791                 _DBG("elm_config_preferred_engine_set is not called");
792         }
793
794         r = appcore_init(ui->name, &efl_ops, *argc, *argv);
795         _retv_if(r == -1, -1);
796
797         LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:appcore_init:done]", ui->name);
798         if (ui->ops && ui->ops->create) {
799                 r = ui->ops->create(ui->ops->data);
800                 if (r == -1) {
801                         _ERR("create() return error");
802                         appcore_exit();
803                         errno = ECANCELED;
804                         return -1;
805                 }
806                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]",
807                     ui->name);
808         }
809         ui->state = AS_CREATED;
810
811         __add_climsg_cb(ui);
812
813         return 0;
814 }
815
816 static void __after_loop(struct ui_priv *ui)
817 {
818         appcore_unset_rotation_cb();
819         appcore_exit();
820
821         if (ui->ops && ui->ops->terminate)
822                 ui->ops->terminate(ui->ops->data);
823
824         if (ui->hshow)
825                 ecore_event_handler_del(ui->hshow);
826         if (ui->hhide)
827                 ecore_event_handler_del(ui->hhide);
828         if (ui->hvchange)
829                 ecore_event_handler_del(ui->hvchange);
830
831         __appcore_timer_del(ui);
832
833         elm_shutdown();
834 }
835
836 static int __set_data(struct ui_priv *ui, const char *name,
837                     struct appcore_ops *ops)
838 {
839         if (ui->name) {
840                 _ERR("Mainloop already started");
841                 errno = EINPROGRESS;
842                 return -1;
843         }
844
845         if (name == NULL || name[0] == '\0') {
846                 _ERR("Invalid name");
847                 errno = EINVAL;
848                 return -1;
849         }
850
851         if (ops == NULL) {
852                 _ERR("ops is NULL");
853                 errno = EINVAL;
854                 return -1;
855         }
856
857         ui->name = strdup(name);
858         _retv_if(ui->name == NULL, -1);
859
860         ui->ops = ops;
861
862         ui->mfcb = __appcore_efl_memory_flush_cb;
863
864         _pid = getpid();
865
866         /* WM_ROTATE */
867         ui->wm_rot_supported = 0;
868         ui->rot_started = 0;
869         ui->rot_cb = NULL;
870         ui->rot_cb_data = NULL;
871         ui->rot_mode = APPCORE_RM_UNKNOWN;
872
873         return 0;
874 }
875
876 static void __unset_data(struct ui_priv *ui)
877 {
878         if (ui->name)
879                 free((void *)ui->name);
880
881         memset(ui, 0, sizeof(struct ui_priv));
882 }
883
884 /* WM_ROTATE */
885 static int __wm_set_rotation_cb(int (*cb) (enum appcore_rm, void *), void *data)
886 {
887         if (cb == NULL) {
888                 errno = EINVAL;
889                 return -1;
890         }
891
892         if ((priv.wm_rot_supported) && (0 == priv.rot_started)) {
893                 __set_wm_rotation_support(0, 1);
894         }
895
896         priv.rot_cb = cb;
897         priv.rot_cb_data = data;
898         priv.rot_started = 1;
899
900         return 0;
901 }
902
903 static int __wm_unset_rotation_cb(void)
904 {
905         if ((priv.wm_rot_supported) && (1 == priv.rot_started)) {
906                 __set_wm_rotation_support(0, 0);
907         }
908
909         priv.rot_cb = NULL;
910         priv.rot_cb_data = NULL;
911         priv.rot_started = 0;
912
913         return 0;
914 }
915
916 static int __wm_get_rotation_state(enum appcore_rm *curr)
917 {
918         if (curr == NULL) {
919                 errno = EINVAL;
920                 return -1;
921         }
922
923         *curr = priv.rot_mode;
924
925         return 0;
926 }
927
928 static int __wm_pause_rotation_cb(void)
929 {
930         if ((1 == priv.rot_started) && (priv.wm_rot_supported)) {
931                 __set_wm_rotation_support(0, 0);
932         }
933
934         priv.rot_started = 0;
935
936         return 0;
937 }
938
939 static int __wm_resume_rotation_cb(void)
940 {
941         if ((0 == priv.rot_started) && (priv.wm_rot_supported)) {
942                 __set_wm_rotation_support(0, 1);
943         }
944
945         priv.rot_started = 1;
946
947         return 0;
948 }
949
950 static struct ui_wm_rotate wm_rotate = {
951         __wm_set_rotation_cb,
952         __wm_unset_rotation_cb,
953         __wm_get_rotation_state,
954         __wm_pause_rotation_cb,
955         __wm_resume_rotation_cb
956 };
957
958 EXPORT_API int appcore_efl_main(const char *name, int *argc, char ***argv,
959                                 struct appcore_ops *ops)
960 {
961         int r;
962
963         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", name);
964
965         r = __set_data(&priv, name, ops);
966         _retv_if(r == -1, -1);
967
968         r = __before_loop(&priv, argc, argv);
969         if (r == -1) {
970                 __unset_data(&priv);
971                 return -1;
972         }
973
974         elm_run();
975
976         aul_status_update(STATUS_DYING);
977
978         __after_loop(&priv);
979
980         __unset_data(&priv);
981
982         return 0;
983 }
984
985 EXPORT_API int appcore_set_system_resource_reclaiming(bool enable)
986 {
987         resource_reclaiming = enable;
988
989         return 0;
990 }
991
992 EXPORT_API int appcore_set_app_state(int state)
993 {
994         priv.state = state;
995
996         tmp_val = 1;
997
998         return 0;
999 }