tizen 2.3 release
[framework/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 #include <X11/Xatom.h>
32 #include <X11/Xlib.h>
33 #include <X11/Xutil.h>
34 #include <X11/extensions/Xcomposite.h>
35 #include <X11/extensions/XShm.h>
36 #include <sys/shm.h>
37 #ifdef WEARABLE
38 #include <proc_stat.h>
39 #endif
40
41 #include <Ecore_X.h>
42 #include <Ecore.h>
43 #include <Ecore_Evas.h>
44 #include <Evas.h>
45 #include <Ecore_Input_Evas.h>
46 #include <Elementary.h>
47 #include <glib-object.h>
48 #include <malloc.h>
49 #include <glib.h>
50 #include <stdbool.h>
51 #include <aul.h>
52 #include "appcore-internal.h"
53 #include "appcore-efl.h"
54 #include "virtual_canvas.h"
55 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
56 #include <vconf/vconf.h>
57 #endif
58
59 #define SYSMAN_MAXSTR 100
60 #define SYSMAN_MAXARG 16
61 #define SYSNOTI_SOCKET_PATH "/tmp/sn"
62 #define RETRY_READ_COUNT        10
63 #define MAX_PACKAGE_STR_SIZE 512
64
65 #define PREDEF_BACKGRD                          "backgrd"
66 #define PREDEF_FOREGRD                          "foregrd"
67
68 enum sysnoti_cmd {
69         ADD_SYSMAN_ACTION,
70         CALL_SYSMAN_ACTION
71 };
72
73 struct sysnoti {
74         int pid;
75         int cmd;
76         char *type;
77         char *path;
78         int argc;
79         char *argv[SYSMAN_MAXARG];
80 };
81
82 static pid_t _pid;
83
84 static bool resource_reclaiming = TRUE;
85 static bool prelaunching = FALSE;
86
87
88
89 struct ui_priv {
90         const char *name;
91         enum app_state state;
92
93         Ecore_Event_Handler *hshow;
94         Ecore_Event_Handler *hhide;
95         Ecore_Event_Handler *hvchange;
96         Ecore_Event_Handler *hcmsg; /* WM_ROTATE */
97
98         Ecore_Timer *mftimer;   /* Ecore Timer for memory flushing */
99
100         struct appcore_ops *ops;
101         void (*mfcb) (void);    /* Memory Flushing Callback */
102
103         /* WM_ROTATE */
104         int wm_rot_supported;
105         int rot_started;
106         int (*rot_cb) (void *event_info, enum appcore_rm, void *);
107         void *rot_cb_data;
108         enum appcore_rm rot_mode;
109 };
110
111 static struct ui_priv priv;
112
113 static const char *_ae_name[AE_MAX] = {
114         [AE_UNKNOWN] = "UNKNOWN",
115         [AE_CREATE] = "CREATE",
116         [AE_TERMINATE] = "TERMINATE",
117         [AE_PAUSE] = "PAUSE",
118         [AE_RESUME] = "RESUME",
119         [AE_RESET] = "RESET",
120         [AE_LOWMEM_POST] = "LOWMEM_POST",
121         [AE_MEM_FLUSH] = "MEM_FLUSH",
122 };
123
124 static const char *_as_name[] = {
125         [AS_NONE] = "NONE",
126         [AS_CREATED] = "CREATED",
127         [AS_RUNNING] = "RUNNING",
128         [AS_PAUSED] = "PAUSED",
129         [AS_DYING] = "DYING",
130 };
131
132 static int b_active = -1;
133 static bool first_launch = 1;
134 static int is_legacy_lifecycle = 0;
135
136 struct win_node {
137         unsigned int win;
138         bool bfobscured;
139 };
140
141 static struct ui_wm_rotate wm_rotate;
142
143 static inline int send_int(int fd, int val)
144 {
145         return write(fd, &val, sizeof(int));
146 }
147
148 static inline int send_str(int fd, char *str)
149 {
150         int len;
151         int ret;
152         if (str == NULL) {
153                 len = 0;
154                 ret = write(fd, &len, sizeof(int));
155         } else {
156                 len = strlen(str);
157                 if (len > SYSMAN_MAXSTR)
158                         len = SYSMAN_MAXSTR;
159                 write(fd, &len, sizeof(int));
160                 ret = write(fd, str, len);
161         }
162         return ret;
163 }
164
165 static int sysnoti_send(struct sysnoti *msg)
166 {
167         int client_len;
168         int client_sockfd;
169         int result;
170         int r;
171         int retry_count = 0;
172         struct sockaddr_un clientaddr;
173         int i;
174
175         client_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
176         if (client_sockfd == -1) {
177                 _ERR("%s: socket create failed\n", __FUNCTION__);
178                 return -1;
179         }
180         bzero(&clientaddr, sizeof(clientaddr));
181         clientaddr.sun_family = AF_UNIX;
182         strncpy(clientaddr.sun_path, SYSNOTI_SOCKET_PATH, sizeof(clientaddr.sun_path) - 1);
183         client_len = sizeof(clientaddr);
184
185         if (connect(client_sockfd, (struct sockaddr *)&clientaddr, client_len) <
186             0) {
187                 _ERR("%s: connect failed\n", __FUNCTION__);
188                 close(client_sockfd);
189                 return -1;
190         }
191
192         send_int(client_sockfd, msg->pid);
193         send_int(client_sockfd, msg->cmd);
194         send_str(client_sockfd, msg->type);
195         send_str(client_sockfd, msg->path);
196         send_int(client_sockfd, msg->argc);
197         for (i = 0; i < msg->argc; i++)
198                 send_str(client_sockfd, msg->argv[i]);
199
200         while (retry_count < RETRY_READ_COUNT) {
201                 r = read(client_sockfd, &result, sizeof(int));
202                 if (r < 0) {
203                         if (errno == EINTR) {
204                                 _ERR("Re-read for error(EINTR)");
205                                 retry_count++;
206                                 continue;
207                         }
208                         _ERR("Read fail for str length");
209                         result = -1;
210                         break;
211
212                 }
213                 break;
214         }
215         if (retry_count == RETRY_READ_COUNT) {
216                 _ERR("Read retry failed");
217         }
218
219         close(client_sockfd);
220         return result;
221 }
222
223 void __trm_app_info_send_socket(char *write_buf)
224 {
225         const char trm_socket_for_app_info[] = "/dev/socket/app_info";
226         int socket_fd = 0;
227         int ret = 0;
228         struct sockaddr_un addr;
229
230         _DBG("__trm_app_info_send_socket");
231
232         if (access(trm_socket_for_app_info, F_OK) != 0) {
233                 _ERR("access");
234                 goto trm_end;
235         }
236
237         socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
238         if (socket_fd < 0) {
239                 _ERR("socket");
240                 goto trm_end;
241         }
242
243         memset(&addr, 0, sizeof(addr));
244         sprintf(addr.sun_path, "%s", trm_socket_for_app_info);
245         addr.sun_family = AF_LOCAL;
246
247         ret = connect(socket_fd, (struct sockaddr *) &addr ,sizeof(sa_family_t) + strlen(trm_socket_for_app_info) );
248         if (ret != 0) {
249                 close(socket_fd);
250                 goto trm_end;
251         }
252
253         send(socket_fd, write_buf, strlen(write_buf), MSG_DONTWAIT | MSG_NOSIGNAL);
254         _DBG("send");
255
256         close(socket_fd);
257 trm_end:
258         return;
259 }
260
261 #ifdef _APPFW_FEATURE_CPU_BOOST
262 static void __stop_cpu_boost(void)
263 {
264         const char trm_sock_for_cpu_boost[] = "/dev/socket/scenario_info";
265         int sock_fd = 0;
266         int ret = 0;
267         struct sockaddr_un addr;
268         const char command[] = "AppLaunchUnlock";
269
270         _DBG("__stop_cpu_boost enter");
271
272         if (access(trm_sock_for_cpu_boost, F_OK) != 0) {
273                 _ERR("access() failed, errno: %d (%s)", errno, strerror(errno));
274                 goto error;
275         }
276
277         sock_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
278         if (sock_fd < 0) {
279                 _ERR("socket() failed, errno: %d (%s)", errno, strerror(errno));
280                 goto error;
281         }
282
283         memset(&addr, 0, sizeof(addr));
284         sprintf(addr.sun_path, "%s", trm_sock_for_cpu_boost);
285         addr.sun_family = AF_LOCAL;
286
287         ret = connect(sock_fd, (struct sockaddr *) &addr, sizeof(sa_family_t) + strlen(trm_sock_for_cpu_boost));
288         if (ret != 0) {
289                 _ERR("connect() failed, errno: %d (%s)", errno, strerror(errno));
290                 close(sock_fd);
291                 goto error;
292         }
293
294         ret = send(sock_fd, command, strlen(command), MSG_DONTWAIT | MSG_NOSIGNAL);
295         if (ret < 0) {
296                 _ERR("send() failed, errno: %d (%s)", errno, strerror(errno));
297                 close(sock_fd);
298                 goto error;
299         }
300
301         close(sock_fd);
302         _DBG("__stop_cpu_boost ok");
303
304 error:
305         return;
306 }
307 #endif
308
309 static int _call_predef_action(const char *type, int num, ...)
310 {
311         struct sysnoti *msg;
312         int ret;
313         va_list argptr;
314
315         int i;
316         char *args = NULL;
317
318         if (type == NULL || num > SYSMAN_MAXARG) {
319                 errno = EINVAL;
320                 return -1;
321         }
322
323         msg = malloc(sizeof(struct sysnoti));
324
325         if (msg == NULL) {
326                 /* Do something for not enought memory error */
327                 return -1;
328         }
329
330         msg->pid = getpid();
331         msg->cmd = CALL_SYSMAN_ACTION;
332         msg->type = (char *)type;
333         msg->path = NULL;
334
335         msg->argc = num;
336         va_start(argptr, num);
337         for (i = 0; i < num; i++) {
338                 args = va_arg(argptr, char *);
339                 msg->argv[i] = args;
340         }
341         va_end(argptr);
342
343         ret = sysnoti_send(msg);
344         free(msg);
345
346         return ret;
347 }
348
349 static int _inform_foregrd(void)
350 {
351         char buf[255];
352         snprintf(buf, sizeof(buf), "%d", getpid());
353         return _call_predef_action(PREDEF_FOREGRD, 1, buf);
354 }
355
356 static int _inform_backgrd(void)
357 {
358         char buf[255];
359         snprintf(buf, sizeof(buf), "%d", getpid());
360         return _call_predef_action(PREDEF_BACKGRD, 1, buf);
361 }
362
363
364
365 char appid[APPID_MAX];
366
367 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
368 bool taskmanage;
369 static void _capture_and_make_file(Ecore_X_Window win, int pid, const char *package);
370 #endif
371
372 static bool __check_skip(Ecore_X_Window xwin);
373
374
375 static int WIN_COMP(gconstpointer data1, gconstpointer data2)
376 {
377         struct win_node *a = (struct win_node *)data1;
378         struct win_node *b = (struct win_node *)data2;
379         return (int)((a->win)-(b->win));
380 }
381
382 GSList *g_winnode_list = NULL;
383
384 #if defined(MEMORY_FLUSH_ACTIVATE)
385 static Eina_Bool __appcore_memory_flush_cb(void *data)
386 {
387         struct ui_priv *ui = (struct ui_priv *)data;
388
389         appcore_flush_memory();
390         ui->mftimer = NULL;
391
392         return ECORE_CALLBACK_CANCEL;
393 }
394
395 static int __appcore_low_memory_post_cb(struct ui_priv *ui)
396 {
397         if (ui->state == AS_PAUSED) {
398         //      appcore_flush_memory();
399         } else {
400                 malloc_trim(0);
401         }
402
403         return 0;
404 }
405
406 static void __appcore_timer_add(struct ui_priv *ui)
407 {
408         ui->mftimer = ecore_timer_add(5, __appcore_memory_flush_cb, ui);
409 }
410
411 static void __appcore_timer_del(struct ui_priv *ui)
412 {
413         if (ui->mftimer) {
414                 ecore_timer_del(ui->mftimer);
415                 ui->mftimer = NULL;
416         }
417 }
418
419 #else
420
421 static int __appcore_low_memory_post_cb(ui_priv *ui)
422 {
423         return -1;
424 }
425
426 #define __appcore_timer_add(ui) 0
427 #define __appcore_timer_del(ui) 0
428
429 #endif
430
431 static void __appcore_efl_memory_flush_cb(void)
432 {
433         //_DBG("[APP %d]   __appcore_efl_memory_flush_cb()", _pid);
434         elm_cache_all_flush();
435 }
436
437 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
438 static Eina_Bool __appcore_mimiapp_capture_cb(void *data)
439 {
440         GSList *iter = NULL;
441         struct win_node *entry = NULL;
442
443         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
444                 entry = iter->data;
445                 if(__check_skip(entry->win) == FALSE)
446                         break;
447         }
448         if(iter) {
449                 entry = iter->data;
450                 if(taskmanage) {
451                         _capture_and_make_file(entry->win, getpid(), appid);
452                 }
453         }
454
455         return ECORE_CALLBACK_CANCEL;
456 }
457 #endif
458
459 static void __do_app(enum app_event event, void *data, bundle * b)
460 {
461         int r = -1;
462         struct ui_priv *ui = data;
463         char trm_buf[MAX_PACKAGE_STR_SIZE];
464 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
465         const char *miniapp = NULL;
466 #endif
467
468         _ret_if(ui == NULL || event >= AE_MAX);
469         _DBG("[APP %d] Event: %s State: %s", _pid, _ae_name[event],
470              _as_name[ui->state]);
471
472         if (event == AE_MEM_FLUSH) {
473                 ui->mfcb();
474                 return;
475         }
476
477         if (event == AE_LOWMEM_POST) {
478                 if (__appcore_low_memory_post_cb(ui) == 0)
479                         return;
480         }
481
482         if (!(ui->state == AS_PAUSED && event == AE_PAUSE))
483                 __appcore_timer_del(ui);
484
485         if (event == AE_TERMINATE) {
486                 _DBG("[APP %d] TERMINATE", _pid);
487                 ui->state = AS_DYING;
488                 elm_exit();
489                 return;
490         }
491
492         _ret_if(ui->ops == NULL);
493
494         switch (event) {
495         case AE_RESET:
496                 _DBG("[APP %d] RESET", _pid);
497                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]",
498                         ui->name);
499                 if (ui->ops->reset)
500                         r = ui->ops->reset(b, ui->ops->data);
501                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]", ui->name);
502
503                 if(first_launch) {
504                         first_launch = 0;
505                         is_legacy_lifecycle = aul_get_support_legacy_lifecycle();
506
507                         _INFO("Legacy lifecycle: %d", is_legacy_lifecycle);
508                         if (!is_legacy_lifecycle) {
509                                 _INFO("[APP %d] Initial Launching, call the resume_cb", _pid);
510                                 if (ui->ops->resume)
511                                         r = ui->ops->resume(ui->ops->data);
512                         }
513                 } else {
514                         _INFO("Legacy lifecycle: %d", is_legacy_lifecycle);
515                         if (!is_legacy_lifecycle) {
516                                 _INFO("[APP %d] App already running, raise the window", _pid);
517                                 x_raise_win(getpid());
518
519                                 if (ui->state == AS_PAUSED) {
520                                         _INFO("[APP %d] Call the resume_cb", _pid);
521                                         if (ui->ops->resume)
522                                                 r = ui->ops->resume(ui->ops->data);
523                                 }
524                         }
525                 }
526
527                 ui->state = AS_RUNNING;
528
529 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
530                 miniapp = bundle_get_val(b, "http://tizen.org/appcontrol/data/miniapp");
531                 if(miniapp && strncmp(miniapp, "on", 2) == 0) {
532                         ecore_timer_add(0.5, __appcore_mimiapp_capture_cb, NULL);
533                 }
534 #endif
535                 break;
536         case AE_PAUSE:
537                 if (ui->state == AS_RUNNING) {
538                         _DBG("[APP %d] PAUSE", _pid);
539                         if (ui->ops->pause)
540                                 r = ui->ops->pause(ui->ops->data);
541                         ui->state = AS_PAUSED;
542                         if(r >= 0 && resource_reclaiming == TRUE)
543                                 __appcore_timer_add(ui);
544                 }
545                 /* TODO : rotation stop */
546                 //r = appcore_pause_rotation_cb();
547
548                 snprintf(trm_buf, MAX_PACKAGE_STR_SIZE, "appinfo_pause:[PID]%d", getpid());
549                 __trm_app_info_send_socket(trm_buf);
550 #ifdef WEARABLE
551                 proc_group_change_status(PROC_CGROUP_SET_BACKGRD, getpid(), NULL);
552 #endif
553                 //_inform_backgrd();
554                 break;
555         case AE_RESUME:
556                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]",
557                     ui->name);
558                 if (ui->state == AS_PAUSED) {
559                         _DBG("[APP %d] RESUME", _pid);
560                         if (ui->ops->resume)
561                                 r = ui->ops->resume(ui->ops->data);
562                         ui->state = AS_RUNNING;
563                 }
564                 /*TODO : rotation start*/
565                 //r = appcore_resume_rotation_cb();
566                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]",
567                     ui->name);
568                 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]",
569                     ui->name);
570
571 #ifdef _GATE_TEST_ENABLE
572                 if(strncmp(ui->name, "wrt-client", 10) != 0) {
573                         LOG(LOG_DEBUG, "GATE-M", "<GATE-M>APP_FULLY_LOADED_%s<GATE-M>", ui->name);
574                 }
575 #endif
576
577 #ifdef WEARABLE
578                 proc_group_change_status(PROC_CGROUP_SET_FOREGRD, getpid(), NULL);
579 #endif
580                 snprintf(trm_buf, MAX_PACKAGE_STR_SIZE,"appinfo_resume:[PID]%d", getpid());
581                 __trm_app_info_send_socket(trm_buf);
582 #ifdef _APPFW_FEATURE_CPU_BOOST
583                 __stop_cpu_boost();
584 #endif
585                 //_inform_foregrd();
586
587                 break;
588         default:
589                 /* do nothing */
590                 break;
591         }
592 }
593
594 static struct ui_ops efl_ops = {
595         .data = &priv,
596         .cb_app = __do_app,
597 };
598
599
600 static bool __check_visible(void)
601 {
602         GSList *iter = NULL;
603         struct win_node *entry = NULL;
604
605         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
606                 entry = iter->data;
607                 //_DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
608                 if(entry->bfobscured == FALSE)
609                         return TRUE;
610         }
611         return FALSE;
612 }
613
614 static bool __check_skip(Ecore_X_Window xwin)
615 {
616         unsigned int i, num;
617         Ecore_X_Window_State *state;
618         int ret;
619
620         ret = ecore_x_netwm_window_state_get(xwin, &state, &num);
621         _DBG("ret(%d), win(%x), state(%x), num(%d)", ret, xwin, state, num);
622         if (state) {
623                 for (i = 0; i < num; i++) {
624                         _DBG("state[%d] : %d", i, state[i]);
625                         switch (state[i]) {
626                                 case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
627                                         free(state);
628                                         return TRUE;
629                                         break;
630                                 case ECORE_X_WINDOW_STATE_SKIP_PAGER:
631                                         free(state);
632                                         return TRUE;
633                                         break;
634                                 default:
635                                         /* Ignore */
636                                         break;
637                         }
638                 }
639         }
640         free(state);
641         return FALSE;
642 }
643
644 static bool __exist_win(unsigned int win)
645 {
646         struct win_node temp;
647         GSList *f;
648
649         temp.win = win;
650
651         f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
652         if (f == NULL) {
653                 return FALSE;
654         } else {
655                 return TRUE;
656         }
657
658 }
659
660 static bool __add_win(unsigned int win)
661 {
662         struct win_node *t;
663         GSList *f;
664
665         t = calloc(1, sizeof(struct win_node));
666         if (t == NULL)
667                 return FALSE;
668
669         t->win = win;
670         t->bfobscured = TRUE;
671
672         _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
673
674         f = g_slist_find_custom(g_winnode_list, t, WIN_COMP);
675
676         if (f) {
677                 errno = ENOENT;
678                 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
679                 free(t);
680                 return 0;
681         }
682
683         g_winnode_list = g_slist_append(g_winnode_list, t);
684
685         return TRUE;
686
687 }
688
689 static bool __delete_win(unsigned int win)
690 {
691         struct win_node temp;
692         GSList *f;
693
694         temp.win = win;
695
696         f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
697         if (f == NULL) {
698                 errno = ENOENT;
699                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
700                      win);
701                 return 0;
702         }
703
704         free(f->data);
705         g_winnode_list = g_slist_delete_link(g_winnode_list, f);
706
707         return TRUE;
708 }
709
710 static bool __update_win(unsigned int win, bool bfobscured)
711 {
712         struct win_node temp;
713         GSList *f;
714
715         struct win_node *t;
716
717         _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
718              bfobscured);
719
720         temp.win = win;
721
722         f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
723
724         if (f == NULL) {
725                 errno = ENOENT;
726                 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
727                 return FALSE;
728         }
729
730         free(f->data);
731         g_winnode_list = g_slist_delete_link(g_winnode_list, f);
732
733         t = calloc(1, sizeof(struct win_node));
734         if (t == NULL)
735                 return FALSE;
736
737         t->win = win;
738         t->bfobscured = bfobscured;
739
740         g_winnode_list = g_slist_append(g_winnode_list, t);
741
742         return TRUE;
743
744 }
745
746 /* WM_ROTATE */
747 static Ecore_X_Atom _WM_WINDOW_ROTATION_SUPPORTED = 0;
748 static Ecore_X_Atom _WM_WINDOW_ROTATION_CHANGE_REQUEST = 0;
749
750 static int __check_wm_rotation_support(void)
751 {
752         _DBG("Disable window manager rotation");
753         return -1;
754 #if 0
755         Ecore_X_Window root, win, win2;
756         int ret;
757
758         if (!_WM_WINDOW_ROTATION_SUPPORTED) {
759                 _WM_WINDOW_ROTATION_SUPPORTED =
760                                         ecore_x_atom_get("_E_WINDOW_ROTATION_SUPPORTED");
761         }
762
763         if (!_WM_WINDOW_ROTATION_CHANGE_REQUEST) {
764                 _WM_WINDOW_ROTATION_CHANGE_REQUEST =
765                                         ecore_x_atom_get("_E_WINDOW_ROTATION_CHANGE_REQUEST");
766         }
767
768         root = ecore_x_window_root_first_get();
769         ret = ecore_x_window_prop_xid_get(root,
770                         _WM_WINDOW_ROTATION_SUPPORTED,
771                         ECORE_X_ATOM_WINDOW,
772                         &win, 1);
773         if ((ret == 1) && (win))
774         {
775                 ret = ecore_x_window_prop_xid_get(win,
776                                 _WM_WINDOW_ROTATION_SUPPORTED,
777                                 ECORE_X_ATOM_WINDOW,
778                                 &win2, 1);
779                 if ((ret == 1) && (win2 == win))
780                         return 0;
781         }
782
783         return -1;
784 #endif
785 }
786
787 static void __set_wm_rotation_support(unsigned int win, unsigned int set)
788 {
789         GSList *iter = NULL;
790         struct win_node *entry = NULL;
791
792         if (0 == win) {
793                 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
794                         entry = iter->data;
795                         if (entry->win) {
796                                 ecore_x_window_prop_card32_set(entry->win,
797                                                 _WM_WINDOW_ROTATION_SUPPORTED,
798                                                 &set, 1);
799                         }
800                 }
801         } else {
802                 ecore_x_window_prop_card32_set(win,
803                                 _WM_WINDOW_ROTATION_SUPPORTED,
804                                 &set, 1);
805         }
806 }
807
808 Ecore_X_Atom atom_parent;
809 Ecore_X_Atom xsend_Atom;
810
811 static Eina_Bool __show_cb(void *data, int type, void *event)
812 {
813         Ecore_X_Event_Window_Show *ev;
814         int ret;
815         Ecore_X_Window parent;
816
817         ev = event;
818
819         ret = ecore_x_window_prop_window_get(ev->win, atom_parent, &parent, 1);
820         if (ret != 1)
821         {
822                 // This is child window. Skip!!!
823                 return ECORE_CALLBACK_PASS_ON;
824         }
825
826         _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x\n", ev->win);
827
828         if (!__exist_win((unsigned int)ev->win)) {
829                 /* WM_ROTATE */
830                 if ((priv.wm_rot_supported) && (1 == priv.rot_started)) {
831                         __set_wm_rotation_support(ev->win, 1);
832                 }
833                 __add_win((unsigned int)ev->win);
834         }
835         else
836                 __update_win((unsigned int)ev->win, FALSE);
837
838         return ECORE_CALLBACK_RENEW;
839 }
840
841 static Eina_Bool __hide_cb(void *data, int type, void *event)
842 {
843         Ecore_X_Event_Window_Hide *ev;
844         int bvisibility = 0;
845
846         ev = event;
847
848         _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
849
850         if (__exist_win((unsigned int)ev->win)) {
851                 __delete_win((unsigned int)ev->win);
852
853                 bvisibility = __check_visible();
854                 if (!bvisibility && b_active != 0) {
855                         _DBG(" Go to Pasue state \n");
856                         b_active = 0;
857                         __do_app(AE_PAUSE, data, NULL);
858 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
859                         if(taskmanage) {
860                                 _capture_and_make_file(ev->win, getpid(), appid);
861                         } else if ( aul_is_subapp() ) {
862                                 _capture_and_make_file(ev->win, getpid(), appcore_get_caller_appid());
863                         }
864 #endif
865                 }
866         }
867
868         return ECORE_CALLBACK_RENEW;
869 }
870
871 static Eina_Bool __visibility_cb(void *data, int type, void *event)
872 {
873         Ecore_X_Event_Window_Visibility_Change *ev;
874         int bvisibility = 0;
875 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
876         int lcd_status = 0;
877 #endif
878
879         ev = event;
880
881         __update_win((unsigned int)ev->win, ev->fully_obscured);
882         bvisibility = __check_visible();
883
884         _DBG("bvisibility %d, b_active %d", bvisibility, b_active);
885
886         if (bvisibility && b_active != 1) {
887                 _DBG(" Go to Resume state\n");
888                 b_active = 1;
889
890 #ifdef _APPFW_FEATURE_VISIBILITY_CHECK_BY_LCD_STATUS
891                 vconf_get_int(VCONFKEY_PM_STATE, &lcd_status);
892                 if(lcd_status == VCONFKEY_PM_STATE_LCDOFF) {
893                         return ECORE_CALLBACK_RENEW;
894                 }
895 #endif
896                 __do_app(AE_RESUME, data, NULL);
897         } else if (!bvisibility && (b_active != 0)) {
898                 _DBG(" Go to Pasue state \n");
899                 b_active = 0;
900                 __do_app(AE_PAUSE, data, NULL);
901 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
902                 if(taskmanage) {
903                         _capture_and_make_file(ev->win, getpid(), appid);
904                 } else if ( aul_is_subapp() ) {
905                         _capture_and_make_file(ev->win, getpid(), appcore_get_caller_appid());
906                 }
907 #endif
908         } else
909                 _DBG(" No change state \n");
910
911         return ECORE_CALLBACK_RENEW;
912
913 }
914
915 /* WM_ROTATE */
916 static Eina_Bool __cmsg_cb(void *data, int type, void *event)
917 {
918         struct ui_priv *ui = (struct ui_priv *)data;
919         Ecore_X_Event_Client_Message *e = event;
920
921 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
922         if (e->message_type == xsend_Atom) {
923                 _DBG("_E_ILLUME_ATOM_APPCORE_RECAPTURE_REQUEST win(%x)", e->win);
924                 _capture_and_make_file(e->win, getpid(), appid);
925                 return ECORE_CALLBACK_PASS_ON;
926         }
927 #endif
928
929         if (!ui) return ECORE_CALLBACK_PASS_ON;
930         if (e->format != 32) return ECORE_CALLBACK_PASS_ON;
931         if (e->message_type == _WM_WINDOW_ROTATION_CHANGE_REQUEST) {
932                 if ((0 == ui->wm_rot_supported) ||
933                         (0 == ui->rot_started) ||
934                         (NULL == ui->rot_cb)) {
935                         return ECORE_CALLBACK_PASS_ON;
936                 }
937
938                 enum appcore_rm rm;
939                 switch (e->data.l[1])
940                 {
941                         case   0: rm = APPCORE_RM_PORTRAIT_NORMAL;   break;
942                         case  90: rm = APPCORE_RM_LANDSCAPE_REVERSE; break;
943                         case 180: rm = APPCORE_RM_PORTRAIT_REVERSE;  break;
944                         case 270: rm = APPCORE_RM_LANDSCAPE_NORMAL;  break;
945                         default:  rm = APPCORE_RM_UNKNOWN;           break;
946                 }
947
948                 ui->rot_mode = rm;
949
950                 if (APPCORE_RM_UNKNOWN != rm) {
951                         ui->rot_cb((void *)&rm, rm, ui->rot_cb_data);
952                 }
953         }
954
955         return ECORE_CALLBACK_PASS_ON;
956 }
957
958 static void __add_climsg_cb(struct ui_priv *ui)
959 {
960         _ret_if(ui == NULL);
961
962         atom_parent = ecore_x_atom_get("_E_PARENT_BORDER_WINDOW");
963         if (!atom_parent)
964         {
965                 // Do Error Handling
966                 _ERR("atom_parent is NULL");
967         }
968         xsend_Atom = ecore_x_atom_get("_E_ILLUME_ATOM_APPCORE_RECAPTURE_REQUEST");
969         if (!xsend_Atom)
970         {
971                 // Do Error Handling
972                 _ERR("xsend_Atom is NULL");
973         }
974
975         ui->hshow = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, __show_cb, ui);
976         ui->hhide = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, __hide_cb, ui);
977         ui->hvchange = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, __visibility_cb, ui);
978
979 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
980         ui->hcmsg = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, __cmsg_cb, ui);
981 #endif
982
983         /* Add client message callback for WM_ROTATE */
984         if(!__check_wm_rotation_support())
985         {
986                 //ui->hcmsg = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, __cmsg_cb, ui);
987                 ui->wm_rot_supported = 1;
988                 appcore_set_wm_rotation(&wm_rotate);
989         }
990 }
991
992 static int __before_loop(struct ui_priv *ui, int *argc, char ***argv)
993 {
994         int r;
995         char *hwacc = NULL;
996         char *tm_tmp = NULL;
997
998         if (argc == NULL || argv == NULL) {
999                 _ERR("argc/argv is NULL");
1000                 errno = EINVAL;
1001                 return -1;
1002         }
1003
1004         g_type_init();
1005         elm_init(*argc, *argv);
1006
1007         hwacc = getenv("HWACC");
1008         if(hwacc == NULL) {
1009                 _DBG("elm_config_preferred_engine_set is not called");
1010         } else if(strcmp(hwacc, "USE") == 0) {
1011                 elm_config_preferred_engine_set("opengl_x11");
1012                 _DBG("elm_config_preferred_engine_set : opengl_x11");
1013         } else if(strcmp(hwacc, "NOT_USE") == 0) {
1014                 elm_config_preferred_engine_set("software_x11");
1015                 _DBG("elm_config_preferred_engine_set : software_x11");
1016         } else {
1017                 _DBG("elm_config_preferred_engine_set is not called");
1018         }
1019 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
1020         tm_tmp = getenv("TASKMANAGE");
1021         if(tm_tmp == NULL) {
1022                 _DBG("taskmanage is null");
1023                 taskmanage = 1;
1024         } else if(strcmp(tm_tmp, "false") == 0) {
1025                 _DBG("taskmanage is false");
1026                 taskmanage = 0;
1027         } else {
1028                 _DBG("taskmanage is true %s", tm_tmp);
1029                 taskmanage = 1;
1030         }
1031 #endif
1032         r = appcore_init(ui->name, &efl_ops, *argc, *argv);
1033         _retv_if(r == -1, -1);
1034
1035         LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:appcore_init:done]", ui->name);
1036         if (ui->ops && ui->ops->create) {
1037                 r = ui->ops->create(ui->ops->data);
1038                 if (r == -1) {
1039                         _ERR("create() return error");
1040                         appcore_exit();
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                         ui->ops->pause(ui->ops->data);
1063         }
1064
1065         if (ui->ops && ui->ops->terminate)
1066                 ui->ops->terminate(ui->ops->data);
1067
1068         if (ui->hshow)
1069                 ecore_event_handler_del(ui->hshow);
1070         if (ui->hhide)
1071                 ecore_event_handler_del(ui->hhide);
1072         if (ui->hvchange)
1073                 ecore_event_handler_del(ui->hvchange);
1074
1075         __appcore_timer_del(ui);
1076
1077         elm_shutdown();
1078
1079 #ifdef _GATE_TEST_ENABLE
1080         if((ui->name) && (strncmp(ui->name, "wrt-client", 10) != 0)) {
1081                 LOG(LOG_DEBUG, "GATE-M", "<GATE-M>APP_CLOSED_%s<GATE-M>", ui->name);
1082         }
1083 #endif
1084 }
1085
1086 static int __set_data(struct ui_priv *ui, const char *name,
1087                     struct appcore_ops *ops)
1088 {
1089         if (ui->name) {
1090                 _ERR("Mainloop already started");
1091                 errno = EINPROGRESS;
1092                 return -1;
1093         }
1094
1095         if (name == NULL || name[0] == '\0') {
1096                 _ERR("Invalid name");
1097                 errno = EINVAL;
1098                 return -1;
1099         }
1100
1101         if (ops == NULL) {
1102                 _ERR("ops is NULL");
1103                 errno = EINVAL;
1104                 return -1;
1105         }
1106
1107         ui->name = strdup(name);
1108         _retv_if(ui->name == NULL, -1);
1109
1110         ui->ops = ops;
1111
1112         ui->mfcb = __appcore_efl_memory_flush_cb;
1113
1114         _pid = getpid();
1115
1116         /* WM_ROTATE */
1117         ui->wm_rot_supported = 0;
1118         ui->rot_started = 0;
1119         ui->rot_cb = NULL;
1120         ui->rot_cb_data = NULL;
1121         ui->rot_mode = APPCORE_RM_UNKNOWN;
1122
1123         return 0;
1124 }
1125
1126 static void __unset_data(struct ui_priv *ui)
1127 {
1128         if (ui->name)
1129                 free((void *)ui->name);
1130
1131         memset(ui, 0, sizeof(struct ui_priv));
1132 }
1133
1134 /* WM_ROTATE */
1135 static int __wm_set_rotation_cb(int (*cb) (void *event_info, enum appcore_rm, void *), void *data)
1136 {
1137         if (cb == NULL) {
1138                 errno = EINVAL;
1139                 return -1;
1140         }
1141
1142         if ((priv.wm_rot_supported) && (0 == priv.rot_started)) {
1143                 __set_wm_rotation_support(0, 1);
1144         }
1145
1146         priv.rot_cb = cb;
1147         priv.rot_cb_data = data;
1148         priv.rot_started = 1;
1149
1150         return 0;
1151 }
1152
1153 static int __wm_unset_rotation_cb(void)
1154 {
1155         if ((priv.wm_rot_supported) && (1 == priv.rot_started)) {
1156                 __set_wm_rotation_support(0, 0);
1157         }
1158
1159         priv.rot_cb = NULL;
1160         priv.rot_cb_data = NULL;
1161         priv.rot_started = 0;
1162
1163         return 0;
1164 }
1165
1166 static int __wm_get_rotation_state(enum appcore_rm *curr)
1167 {
1168         if (curr == NULL) {
1169                 errno = EINVAL;
1170                 return -1;
1171         }
1172
1173         *curr = priv.rot_mode;
1174
1175         return 0;
1176 }
1177
1178 static int __wm_pause_rotation_cb(void)
1179 {
1180         if ((1 == priv.rot_started) && (priv.wm_rot_supported)) {
1181                 __set_wm_rotation_support(0, 0);
1182         }
1183
1184         priv.rot_started = 0;
1185
1186         return 0;
1187 }
1188
1189 static int __wm_resume_rotation_cb(void)
1190 {
1191         if ((0 == priv.rot_started) && (priv.wm_rot_supported)) {
1192                 __set_wm_rotation_support(0, 1);
1193         }
1194
1195         priv.rot_started = 1;
1196
1197         return 0;
1198 }
1199
1200 static struct ui_wm_rotate wm_rotate = {
1201         __wm_set_rotation_cb,
1202         __wm_unset_rotation_cb,
1203         __wm_get_rotation_state,
1204         __wm_pause_rotation_cb,
1205         __wm_resume_rotation_cb
1206 };
1207
1208 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
1209 static Window _get_parent_window(Window id)
1210 {
1211         Window root;
1212         Window parent;
1213         Window *children;
1214         unsigned int num;
1215
1216         if (!XQueryTree(ecore_x_display_get(), id, &root, &parent, &children, &num)) {
1217                 return 0;
1218         }
1219
1220         if (children) {
1221                 XFree(children);
1222         }
1223
1224         return parent;
1225 }
1226
1227 static Window _find_capture_window(Window id, Visual **visual, int *depth, int *width, int *height)
1228 {
1229         XWindowAttributes attr;
1230         Window parent = id;
1231         Window orig_id = id;
1232
1233         if (id == 0) {
1234                 return (Window)-1;
1235         }
1236
1237         do {
1238                 id = parent;
1239
1240                 if (!XGetWindowAttributes(ecore_x_display_get(), id, &attr)) {
1241                         return (Window)-1;
1242                 }
1243
1244                 parent = _get_parent_window(id);
1245
1246                 if (attr.map_state == IsViewable
1247                     && attr.override_redirect == True
1248                     && attr.class == InputOutput && parent == attr.root) {
1249                         *depth = attr.depth;
1250                         *width = attr.width;
1251                         *height = attr.height;
1252                         *visual = attr.visual;
1253                         return id;
1254                 }
1255         } while (parent != attr.root && parent != 0);
1256
1257         XGetWindowAttributes(ecore_x_display_get(), orig_id, &attr);
1258         *depth = attr.depth;
1259         *width = attr.width;
1260         *height = attr.height;
1261         *visual = attr.visual;
1262
1263         return (Window) 0;
1264
1265 }
1266
1267 static char *_capture_window(Window id, Visual *visual, int width, int height, int depth, int *size)
1268 {
1269         XShmSegmentInfo si;
1270         XImage *xim;
1271         int img_size;
1272         char *captured_img = NULL;
1273
1274         /* (depth >> 3) + 1 == 4 byte */
1275         si.shmid =
1276             shmget(IPC_PRIVATE, width * height * ((depth >> 3) + 1),
1277                    IPC_CREAT | 0666);
1278
1279         if (si.shmid < 0) {
1280                 _ERR("shmget");
1281                 return NULL;
1282         }
1283
1284         si.readOnly = False;
1285         si.shmaddr = shmat(si.shmid, NULL, 0);
1286
1287         if (si.shmaddr == (char *)-1) {
1288                 shmdt(si.shmaddr);
1289                 shmctl(si.shmid, IPC_RMID, 0);
1290                 return NULL;
1291         }
1292
1293         xim = XShmCreateImage(ecore_x_display_get(), visual, depth, ZPixmap, NULL, &si,
1294                             width, height);
1295
1296         if (xim == 0) {
1297                 shmdt(si.shmaddr);
1298                 shmctl(si.shmid, IPC_RMID, 0);
1299
1300                 return NULL;
1301         }
1302
1303         img_size = xim->bytes_per_line * xim->height;
1304         xim->data = si.shmaddr;
1305
1306         XSync(ecore_x_display_get(), False);
1307         XShmAttach(ecore_x_display_get(), &si);
1308         XShmGetImage(ecore_x_display_get(), id, xim, 0, 0, 0xFFFFFFFF);
1309         XSync(ecore_x_display_get(), False);
1310
1311         captured_img = calloc(1, img_size);
1312         if (captured_img) {
1313                 memcpy(captured_img, xim->data, img_size);
1314         } else {
1315                 _ERR("calloc");
1316         }
1317
1318         XShmDetach(ecore_x_display_get(), &si);
1319         XDestroyImage(xim);
1320
1321
1322         shmdt(si.shmaddr);
1323         shmctl(si.shmid, IPC_RMID, 0);
1324
1325         *size = img_size;
1326
1327         return captured_img;
1328
1329 }
1330
1331 #define _WND_REQUEST_ANGLE_IDX 0
1332 #define _WND_CURR_ANGLE_IDX    1
1333 int _get_angle(Ecore_X_Window win)
1334 {
1335         int after = -1;
1336         int before = -1;
1337
1338         do {
1339                 int ret, count;
1340                 int angle[2] = {-1, -1};
1341                 unsigned char* prop_data = NULL;
1342
1343                 ret = ecore_x_window_prop_property_get(win,
1344                                 ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE,
1345                                 ECORE_X_ATOM_CARDINAL,
1346                                 32,
1347                                 &prop_data,
1348                                 &count);
1349                 if (ret <= 0) {
1350                         if (prop_data) free(prop_data);
1351                         break;
1352                 }
1353
1354                 if (prop_data) {
1355                         memcpy(&angle, prop_data, sizeof (int) *count);
1356                         free(prop_data);
1357                 }
1358
1359                 after= angle[_WND_REQUEST_ANGLE_IDX];
1360                 before = angle[_WND_CURR_ANGLE_IDX];
1361         } while (0);
1362
1363         if (-1 == after) after = 0;
1364
1365         return after;
1366 }
1367
1368 static void _rotate_img(Evas_Object *image_object, int angle, int cx, int cy)
1369 {
1370         Evas_Map *em;
1371
1372         _ret_if(NULL == image_object);
1373
1374         em = evas_map_new(4);
1375         _ret_if(NULL == em);
1376
1377         evas_map_util_points_populate_from_object(em, image_object);
1378         evas_map_util_rotate(em, (double) angle, cx, cy);
1379
1380         evas_object_map_set(image_object, em);
1381         evas_object_map_enable_set(image_object, EINA_TRUE);
1382
1383         evas_map_free(em);
1384 }
1385
1386 #define EXTENSION_LEN 128
1387 #define CAPTURE_FILE_PATH "/opt/usr/share/app_capture"
1388 bool _make_capture_file(const char *package, int width, int height, char *img, int angle)
1389 {
1390         int len;
1391         char *filename;
1392         Evas *e;
1393         Evas_Object *image_object;
1394         int canvas_width, canvas_height;
1395         int cx = 0, cy = 0;
1396         int mx = 0;
1397         int r = 0;
1398
1399         _retv_if(NULL == package, false);
1400
1401         len = strlen(package) + EXTENSION_LEN;
1402         filename = malloc(len);
1403         _retv_if(NULL == filename, false);
1404         snprintf(filename, len, CAPTURE_FILE_PATH"/%s.jpg", package);
1405
1406         if (90 == angle || 270 == angle) {
1407                 canvas_width = height;
1408                 canvas_height = width;
1409         } else {
1410                 canvas_width = width;
1411                 canvas_height = height;
1412         }
1413
1414         e = virtual_canvas_create(canvas_width, canvas_height);
1415         goto_if(NULL == e, error);
1416
1417         image_object = evas_object_image_add(e);
1418         goto_if(NULL == image_object, error);
1419
1420         evas_object_image_size_set(image_object, width, height);
1421         evas_object_image_data_set(image_object, img);
1422         evas_object_image_data_update_add(image_object, 0, 0, width, height);
1423         evas_object_resize(image_object, width, height);
1424         evas_object_image_filled_set(image_object, EINA_TRUE);
1425         switch (angle) {
1426                 case 90:
1427                         cx = canvas_width - width / 2;
1428                         cy = canvas_height / 2;
1429                         mx = canvas_width - width;
1430                         break;
1431                 case 180:
1432                         cx = width / 2;
1433                         cy = height / 2;
1434                         break;
1435                 case 270:
1436                         cx = width / 2;
1437                         cy = canvas_height / 2;
1438                         break;
1439                 default:
1440                         break;
1441         }
1442         evas_object_move(image_object, mx, 0);
1443         _rotate_img(image_object, angle, cx, cy);
1444         evas_object_show(image_object);
1445
1446         if (access(CAPTURE_FILE_PATH, F_OK) != 0) {
1447                 r = mkdir(CAPTURE_FILE_PATH, 0777);
1448                 goto_if(r < 0, error);
1449         }
1450         goto_if(false == virtual_canvas_flush_to_file(e, filename, canvas_width, canvas_height), error);
1451
1452         evas_object_del(image_object);
1453         virtual_canvas_destroy(e);
1454         free(filename);
1455
1456         return true;
1457
1458 error:
1459         do {
1460                 free(filename);
1461
1462                 if (!e) break;
1463                 virtual_canvas_destroy(e);
1464
1465                 if (!image_object) break;
1466                 evas_object_del(image_object);
1467         } while (0);
1468
1469         return false;
1470 }
1471
1472 int __resize8888(const char* pDataIn, char* pDataOut, int inWidth, int inHeight, int outWidth, int outHeight)
1473 {
1474         int scaleX = 0;
1475         int scaleY = 0;
1476         int i = 0;
1477         int j = 0;
1478         int iRow = 0;
1479         int iIndex = 0;
1480         char* pOutput = pDataOut;
1481         char* pOut = pDataOut;
1482         const char* pIn = NULL;
1483         int *pColLUT = malloc(sizeof(int) * outWidth);
1484
1485         /* Calculate X Scale factor */
1486         scaleX = inWidth * 256 / outWidth;
1487         /* Calculate Y Scale factor, aspect ratio is not maintained */
1488         scaleY = inHeight * 256 / outHeight;
1489         for (j = 0; j < outWidth; j++)
1490         {
1491         /* Get input index based on column scale factor */
1492         /* To get more optimization, this is calculated once and
1493         * is placed in a LUT and used for indexing
1494         */
1495         pColLUT [j] = ((j * scaleX) >> 8) * 4;
1496         }
1497         pOut = pOutput;
1498         for (i = 0; i < outHeight; i++)
1499         {
1500                 /* Get input routWidth index based on routWidth scale factor */
1501                 iRow = (i * scaleY >> 8) * inWidth * 4;
1502                 /* Loop could be unrolled for more optimization */
1503                 for (j = 0; j < (outWidth); j++)
1504                 {
1505                         /* Get input index based on column scale factor */
1506                         iIndex = iRow + pColLUT [j];
1507                         pIn = pDataIn + iIndex;
1508                         *pOut++ = *pIn++;
1509                         *pOut++ = *pIn++;
1510                         *pOut++ = *pIn++;
1511                         *pOut++ = *pIn++;
1512                 }
1513         }
1514
1515         free(pColLUT);
1516         return 0;
1517 }
1518
1519 static void _capture_and_make_file(Ecore_X_Window win, int pid, const char *package)
1520 {
1521         Visual *visual;
1522         Window redirected_id;
1523
1524         int width, height, depth;
1525         int width_out, height_out;
1526         int size = 0;
1527         int angle;
1528
1529         char *img;
1530
1531         redirected_id = _find_capture_window(win, &visual, &depth, &width, &height);
1532         _ret_if(redirected_id == (Window) -1 ||
1533                                 redirected_id == (Window) 0);
1534
1535         SECURE_LOGD("Capture : win[%x] -> redirected win[%x] for %s[%d]", win, redirected_id, package, pid);
1536
1537         img = _capture_window(redirected_id, visual, width, height, depth, &size);
1538         _ret_if(NULL == img);
1539
1540         width_out = width/2;
1541         height_out = height/2;
1542
1543         if ( width_out < 1 || height_out < 1 ) {
1544                 free(img);
1545                 return;
1546         }
1547
1548         __resize8888(img, img, width, height, width_out, height_out);
1549
1550         angle = _get_angle(win);
1551         if (false == _make_capture_file(package, width_out, height_out, img, angle)) {
1552                 _ERR("cannot a capture file for the package of [%s]", package);
1553         }
1554
1555         free(img);
1556 }
1557 #endif
1558
1559 extern int aul_status_update(int status);
1560
1561 EXPORT_API int appcore_efl_main(const char *name, int *argc, char ***argv,
1562                                 struct appcore_ops *ops)
1563 {
1564         int r;
1565         GSList *iter = NULL;
1566         struct win_node *entry = NULL;
1567         int pid;
1568
1569         LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", name);
1570
1571         pid = getpid();
1572         r = aul_app_get_appid_bypid(pid, appid, APPID_MAX);
1573         if( r < 0) {
1574                 _ERR("aul_app_get_appid_bypid fail");
1575         }
1576
1577         r = __set_data(&priv, name, ops);
1578         _retv_if(r == -1, -1);
1579
1580         r = __before_loop(&priv, argc, argv);
1581         if (r == -1) {
1582                 __unset_data(&priv);
1583                 return -1;
1584         }
1585
1586         elm_run();
1587
1588         aul_status_update(STATUS_DYING);
1589
1590 #ifdef _APPFW_FEATURE_CAPTURE_FOR_TASK_MANAGER
1591         for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
1592                 entry = iter->data;
1593                 if(__check_skip(entry->win) == FALSE)
1594                         break;
1595         }
1596         if(iter) {
1597                 entry = iter->data;
1598                 if(taskmanage) {
1599                         _capture_and_make_file(entry->win, pid, appid);
1600                 }
1601         }
1602 #endif
1603
1604         __after_loop(&priv);
1605
1606         __unset_data(&priv);
1607
1608         return 0;
1609 }
1610
1611 EXPORT_API int appcore_set_system_resource_reclaiming(bool enable)
1612 {
1613         resource_reclaiming = enable;
1614
1615         return 0;
1616 }
1617
1618 EXPORT_API int appcore_set_app_state(int state)
1619 {
1620         priv.state = state;
1621
1622         return 0;
1623 }
1624
1625 EXPORT_API int appcore_efl_goto_pause()
1626 {
1627         _DBG(" Go to Pasue state \n");
1628         b_active = 0;
1629         __do_app(AE_PAUSE, &priv, NULL);
1630
1631         return 0;
1632 }
1633
1634 EXPORT_API int appcore_set_prelaunching(bool value)
1635 {
1636         prelaunching = value;
1637
1638         return 0;
1639 }
1640
1641 #ifdef _APPFW_FEATURE_PROCESS_POOL
1642 EXPORT_API int appcore_set_preinit_window_name(const char* win_name)
1643 {
1644         int ret = -1;
1645         void *preinit_window = NULL;
1646
1647         if(!win_name) {
1648                 _ERR("invalid input param");
1649                 return -1;
1650         }
1651
1652         preinit_window = aul_get_preinit_window(win_name);
1653         if(!preinit_window) {
1654                 _ERR("no preinit window");
1655                 return -1;
1656         }
1657
1658         const Evas *e = evas_object_evas_get((const Evas_Object *)preinit_window);
1659         if(e) {
1660                 Ecore_Evas *ee = ecore_evas_ecore_evas_get(e);
1661                 if(ee) {
1662                         ecore_evas_name_class_set(ee, win_name, win_name);
1663                         _DBG("name class set success : %s", win_name);
1664                         ret = 0;
1665                 }
1666         }
1667
1668         return ret;
1669 }
1670 #endif