4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
26 #include <X11/Xatom.h>
30 #include <Ecore_Evas.h>
31 #include <Ecore_Input_Evas.h>
32 #include <Elementary.h>
33 #include <glib-object.h>
38 #include "appcore-internal.h"
39 #include "appcore-efl.h"
43 static bool resource_reclaiming = TRUE;
49 Ecore_Event_Handler *hshow;
50 Ecore_Event_Handler *hhide;
51 Ecore_Event_Handler *hvchange;
52 Ecore_Event_Handler *hcmsg; /* WM_ROTATE */
54 Ecore_Timer *mftimer; /* Ecore Timer for memory flushing */
56 struct appcore_ops *ops;
57 void (*mfcb) (void); /* Memory Flushing Callback */
62 int (*rot_cb) (enum appcore_rm, void *);
64 enum appcore_rm rot_mode;
67 static struct ui_priv priv;
69 static const char *_ae_name[AE_MAX] = {
70 [AE_UNKNOWN] = "UNKNOWN",
71 [AE_CREATE] = "CREATE",
72 [AE_TERMINATE] = "TERMINATE",
74 [AE_RESUME] = "RESUME",
76 [AE_LOWMEM_POST] = "LOWMEM_POST",
77 [AE_MEM_FLUSH] = "MEM_FLUSH",
80 static const char *_as_name[] = {
82 [AS_CREATED] = "CREATED",
83 [AS_RUNNING] = "RUNNING",
84 [AS_PAUSED] = "PAUSED",
88 static bool b_active = 0;
94 static struct ui_wm_rotate wm_rotate;
96 static int WIN_COMP(gconstpointer data1, gconstpointer data2)
98 struct win_node *a = (struct win_node *)data1;
99 struct win_node *b = (struct win_node *)data2;
100 return (int)((a->win)-(b->win));
103 GSList *g_winnode_list = NULL;
105 #if defined(MEMORY_FLUSH_ACTIVATE)
106 static Eina_Bool __appcore_memory_flush_cb(void *data)
108 struct ui_priv *ui = (struct ui_priv *)data;
110 appcore_flush_memory();
113 return ECORE_CALLBACK_CANCEL;
116 static int __appcore_low_memory_post_cb(struct ui_priv *ui)
118 if (ui->state == AS_PAUSED) {
119 appcore_flush_memory();
127 static void __appcore_timer_add(struct ui_priv *ui)
129 ui->mftimer = ecore_timer_add(5, __appcore_memory_flush_cb, ui);
132 static void __appcore_timer_del(struct ui_priv *ui)
135 ecore_timer_del(ui->mftimer);
142 static int __appcore_low_memory_post_cb(ui_priv *ui)
147 #define __appcore_timer_add(ui) 0
148 #define __appcore_timer_del(ui) 0
152 static void __appcore_efl_memory_flush_cb(void)
154 _DBG("[APP %d] __appcore_efl_memory_flush_cb()", _pid);
155 elm_cache_all_flush();
158 static void __do_app(enum app_event event, void *data, bundle * b)
161 struct ui_priv *ui = data;
163 _DBG("[APP %d] Event: %d", _pid, event);
164 _ret_if(ui == NULL || event >= AE_MAX);
165 _DBG("[APP %d] Event: %s State: %s", _pid, _ae_name[event],
166 _as_name[ui->state]);
168 if (event == AE_MEM_FLUSH) {
173 if (event == AE_LOWMEM_POST) {
174 if (__appcore_low_memory_post_cb(ui) == 0)
178 if (!(ui->state == AS_PAUSED && event == AE_PAUSE))
179 __appcore_timer_del(ui);
181 if (event == AE_TERMINATE) {
182 _DBG("[APP %d] TERMINATE", _pid);
183 ui->state = AS_DYING;
188 _ret_if(ui->ops == NULL);
192 _DBG("[APP %d] RESET", _pid);
193 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]",
196 r = ui->ops->reset(b, ui->ops->data);
197 ui->state = AS_RUNNING;
198 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]",
202 if (ui->state == AS_RUNNING) {
203 _DBG("[APP %d] PAUSE", _pid);
205 r = ui->ops->pause(ui->ops->data);
206 ui->state = AS_PAUSED;
207 if(r >= 0 && resource_reclaiming == TRUE)
208 __appcore_timer_add(ui);
210 /* TODO : rotation stop */
211 //r = appcore_pause_rotation_cb();
213 sysman_inform_backgrd();
216 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]",
218 if (ui->state == AS_PAUSED) {
219 _DBG("[APP %d] RESUME", _pid);
221 r = ui->ops->resume(ui->ops->data);
222 ui->state = AS_RUNNING;
224 /*TODO : rotation start*/
225 //r = appcore_resume_rotation_cb();
226 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]",
228 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:Launching:done]",
230 sysman_inform_foregrd();
239 static struct ui_ops efl_ops = {
245 static bool __check_visible(void)
248 struct win_node *entry = NULL;
250 _DBG("[EVENT_TEST][EVENT] __check_visible\n");
252 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
254 _DBG("win : %x obscured : %d\n", entry->win, entry->bfobscured);
255 if(entry->bfobscured == FALSE)
261 static bool __exist_win(unsigned int win)
263 struct win_node temp;
268 f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
277 static bool __add_win(unsigned int win)
282 t = calloc(1, sizeof(struct win_node));
287 t->bfobscured = FALSE;
289 _DBG("[EVENT_TEST][EVENT] __add_win WIN:%x\n", win);
291 f = g_slist_find_custom(g_winnode_list, t, WIN_COMP);
295 _DBG("[EVENT_TEST][EVENT] ERROR There is already window : %x \n", win);
300 g_winnode_list = g_slist_append(g_winnode_list, t);
306 static bool __delete_win(unsigned int win)
308 struct win_node temp;
313 f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
316 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n",
321 g_winnode_list = g_slist_remove_link(g_winnode_list, f);
328 static bool __update_win(unsigned int win, bool bfobscured)
330 struct win_node temp;
335 _DBG("[EVENT_TEST][EVENT] __update_win WIN:%x fully_obscured %d\n", win,
340 f = g_slist_find_custom(g_winnode_list, &temp, WIN_COMP);
344 _DBG("[EVENT_TEST][EVENT] ERROR There is no window : %x \n", win);
348 g_winnode_list = g_slist_remove_link(g_winnode_list, f);
352 t = calloc(1, sizeof(struct win_node));
357 t->bfobscured = bfobscured;
359 g_winnode_list = g_slist_append(g_winnode_list, t);
366 static Ecore_X_Atom _WM_WINDOW_ROTATION_SUPPORTED = 0;
367 static Ecore_X_Atom _WM_WINDOW_ROTATION_CHANGE_REQUEST = 0;
369 static int __check_wm_rotation_support(void)
371 Ecore_X_Window root, win, win2;
374 if (!_WM_WINDOW_ROTATION_SUPPORTED) {
375 _WM_WINDOW_ROTATION_SUPPORTED =
376 ecore_x_atom_get("_E_WINDOW_ROTATION_SUPPORTED");
379 if (!_WM_WINDOW_ROTATION_CHANGE_REQUEST) {
380 _WM_WINDOW_ROTATION_CHANGE_REQUEST =
381 ecore_x_atom_get("_E_WINDOW_ROTATION_CHANGE_REQUEST");
384 root = ecore_x_window_root_first_get();
385 ret = ecore_x_window_prop_xid_get(root,
386 _WM_WINDOW_ROTATION_SUPPORTED,
389 if ((ret == 1) && (win))
391 ret = ecore_x_window_prop_xid_get(win,
392 _WM_WINDOW_ROTATION_SUPPORTED,
395 if ((ret == 1) && (win2 == win))
402 static void __set_wm_rotation_support(unsigned int win, unsigned int set)
405 struct win_node *entry = NULL;
408 for (iter = g_winnode_list; iter != NULL; iter = g_slist_next(iter)) {
411 ecore_x_window_prop_card32_set(entry->win,
412 _WM_WINDOW_ROTATION_SUPPORTED,
417 ecore_x_window_prop_card32_set(win,
418 _WM_WINDOW_ROTATION_SUPPORTED,
423 Ecore_X_Atom atom_parent;
425 static Eina_Bool __show_cb(void *data, int type, void *event)
427 Ecore_X_Event_Window_Show *ev;
429 Ecore_X_Window parent;
433 ret = ecore_x_window_prop_window_get(ev->win, atom_parent, &parent, 1);
436 // This is child window. Skip!!!
437 return ECORE_CALLBACK_PASS_ON;
440 _DBG("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN:%x\n", ev->win);
442 if (!__exist_win((unsigned int)ev->win)) {
444 if ((priv.wm_rot_supported) && (1 == priv.rot_started)) {
445 __set_wm_rotation_support(ev->win, 1);
447 __add_win((unsigned int)ev->win);
450 __update_win((unsigned int)ev->win, FALSE);
452 return ECORE_CALLBACK_RENEW;
455 static Eina_Bool __hide_cb(void *data, int type, void *event)
457 Ecore_X_Event_Window_Hide *ev;
462 _DBG("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN:%x\n", ev->win);
464 if (__exist_win((unsigned int)ev->win)) {
465 __delete_win((unsigned int)ev->win);
467 bvisibility = __check_visible();
468 if (!bvisibility && b_active == 1) {
469 _DBG(" Go to Pasue state \n");
471 __do_app(AE_PAUSE, data, NULL);
475 return ECORE_CALLBACK_RENEW;
478 static Eina_Bool __visibility_cb(void *data, int type, void *event)
480 Ecore_X_Event_Window_Visibility_Change *ev;
485 __update_win((unsigned int)ev->win, ev->fully_obscured);
486 bvisibility = __check_visible();
488 if (bvisibility && b_active == 0) {
489 _DBG(" Go to Resume state\n");
491 __do_app(AE_RESUME, data, NULL);
493 } else if (!bvisibility && b_active == 1) {
494 _DBG(" Go to Pasue state \n");
496 __do_app(AE_PAUSE, data, NULL);
498 _DBG(" No change state \n");
500 return ECORE_CALLBACK_RENEW;
505 static Eina_Bool __cmsg_cb(void *data, int type, void *event)
507 struct ui_priv *ui = (struct ui_priv *)data;
508 Ecore_X_Event_Client_Message *e = event;
510 if (!ui) return ECORE_CALLBACK_PASS_ON;
511 if (e->format != 32) return ECORE_CALLBACK_PASS_ON;
512 if (e->message_type == _WM_WINDOW_ROTATION_CHANGE_REQUEST) {
513 if ((0 == ui->wm_rot_supported) ||
514 (0 == ui->rot_started) ||
515 (NULL == ui->rot_cb)) {
516 return ECORE_CALLBACK_PASS_ON;
520 switch (e->data.l[1])
522 case 0: rm = APPCORE_RM_PORTRAIT_NORMAL; break;
523 case 90: rm = APPCORE_RM_LANDSCAPE_REVERSE; break;
524 case 180: rm = APPCORE_RM_PORTRAIT_REVERSE; break;
525 case 270: rm = APPCORE_RM_LANDSCAPE_NORMAL; break;
526 default: rm = APPCORE_RM_UNKNOWN; break;
531 if (APPCORE_RM_UNKNOWN != rm) {
532 ui->rot_cb(rm, ui->rot_cb_data);
536 return ECORE_CALLBACK_PASS_ON;
539 static void __add_climsg_cb(struct ui_priv *ui)
543 atom_parent = ecore_x_atom_get("_E_PARENT_BORDER_WINDOW");
550 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, __show_cb, ui);
552 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, __hide_cb, ui);
554 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE,
555 __visibility_cb, ui);
557 /* Add client message callback for WM_ROTATE */
558 if(!__check_wm_rotation_support())
561 ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, __cmsg_cb, ui);
562 ui->wm_rot_supported = 1;
563 appcore_set_wm_rotation(&wm_rotate);
567 static int __before_loop(struct ui_priv *ui, int *argc, char ***argv)
572 if (argc == NULL || argv == NULL) {
573 _ERR("argc/argv is NULL");
579 elm_init(*argc, *argv);
581 hwacc = getenv("HWACC");
584 _DBG("elm_config_preferred_engine_set is not called");
585 } else if(strcmp(hwacc, "USE") == 0) {
586 elm_config_preferred_engine_set("opengl_x11");
587 _DBG("elm_config_preferred_engine_set : opengl_x11");
588 } else if(strcmp(hwacc, "NOT_USE") == 0) {
589 elm_config_preferred_engine_set("software_x11");
590 _DBG("elm_config_preferred_engine_set : software_x11");
592 _DBG("elm_config_preferred_engine_set is not called");
595 r = appcore_init(ui->name, &efl_ops, *argc, *argv);
596 _retv_if(r == -1, -1);
598 LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:appcore_init:done]", ui->name);
599 if (ui->ops && ui->ops->create) {
600 r = ui->ops->create(ui->ops->data);
602 _ERR("create() return error");
607 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]",
610 ui->state = AS_CREATED;
617 static void __after_loop(struct ui_priv *ui)
619 appcore_unset_rotation_cb();
622 if (ui->ops && ui->ops->terminate)
623 ui->ops->terminate(ui->ops->data);
626 ecore_event_handler_del(ui->hshow);
628 ecore_event_handler_del(ui->hhide);
630 ecore_event_handler_del(ui->hvchange);
632 __appcore_timer_del(ui);
637 static int __set_data(struct ui_priv *ui, const char *name,
638 struct appcore_ops *ops)
641 _ERR("Mainloop already started");
646 if (name == NULL || name[0] == '\0') {
647 _ERR("Invalid name");
658 ui->name = strdup(name);
659 _retv_if(ui->name == NULL, -1);
663 ui->mfcb = __appcore_efl_memory_flush_cb;
668 ui->wm_rot_supported = 0;
671 ui->rot_cb_data = NULL;
672 ui->rot_mode = APPCORE_RM_UNKNOWN;
677 static void __unset_data(struct ui_priv *ui)
680 free((void *)ui->name);
682 memset(ui, 0, sizeof(struct ui_priv));
686 static int __wm_set_rotation_cb(int (*cb) (enum appcore_rm, void *), void *data)
693 if ((priv.wm_rot_supported) && (0 == priv.rot_started)) {
694 __set_wm_rotation_support(0, 1);
698 priv.rot_cb_data = data;
699 priv.rot_started = 1;
704 static int __wm_unset_rotation_cb(void)
706 if ((priv.wm_rot_supported) && (1 == priv.rot_started)) {
707 __set_wm_rotation_support(0, 0);
711 priv.rot_cb_data = NULL;
712 priv.rot_started = 0;
717 static int __wm_get_rotation_state(enum appcore_rm *curr)
724 *curr = priv.rot_mode;
729 static int __wm_pause_rotation_cb(void)
731 if ((1 == priv.rot_started) && (priv.wm_rot_supported)) {
732 __set_wm_rotation_support(0, 0);
735 priv.rot_started = 0;
740 static int __wm_resume_rotation_cb(void)
742 if ((0 == priv.rot_started) && (priv.wm_rot_supported)) {
743 __set_wm_rotation_support(0, 1);
746 priv.rot_started = 1;
751 static struct ui_wm_rotate wm_rotate = {
752 __wm_set_rotation_cb,
753 __wm_unset_rotation_cb,
754 __wm_get_rotation_state,
755 __wm_pause_rotation_cb,
756 __wm_resume_rotation_cb
759 EXPORT_API int appcore_efl_main(const char *name, int *argc, char ***argv,
760 struct appcore_ops *ops)
764 LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", name);
766 r = __set_data(&priv, name, ops);
767 _retv_if(r == -1, -1);
769 r = __before_loop(&priv, argc, argv);
784 EXPORT_API int appcore_set_system_resource_reclaiming(bool enable)
786 resource_reclaiming = enable;