2 * Copyright 2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <stdlib.h> /* exit */
20 #include <unistd.h> /* access */
26 #include <widget_errno.h>
27 #include <widget_provider.h>
28 #include <widget_provider_buffer.h>
29 #include <widget/widget_internal.h>
30 #include <widget/widget.h>
31 #include <widget_service.h>
32 #include <widget_util.h>
33 #include <widget_service_internal.h>
34 #include <com-core_packet.h>
36 #include "critical_log.h"
38 #include "so_handler.h"
40 #include "update_monitor.h"
43 #include "connection.h"
46 #if defined(_ESTIMATE_PERF)
47 #define ESTIMATE_START(id) DbgPrint("%s START\n", id);
48 #define ESTIMATE_END(id) DbgPrint("%s END\n", id);
50 #define ESTIMATE_START(id)
51 #define ESTIMATE_END(id)
54 #define IS_WIDGET_SHOWN(itm) (!(itm)->inst->item->has_widget_script || ((itm)->inst->item->has_widget_script && (itm)->is_widget_show))
58 #define UPDATE_ITEM_DELETED (-1)
59 #define UPDATE_INVOKED (-2)
60 #define UPDATE_NOT_INVOKED (0)
62 enum gbar_open_state {
63 GBAR_IS_OPENED_BUT_NOT_MINE = -1,
64 GBAR_IS_NOT_OPENED = 0,
76 struct instance *inst;
80 double update_interval;
81 int heavy_updating; /* Only for debugging message */
82 enum state state; /* 1 is paused, 0 is resumed */
85 unsigned int updated_in_pause;
89 int is_widget_updated;
91 Eina_List *direct_path_list;
96 Eina_List *force_update_list;
97 Eina_List *update_list;
98 Eina_List *pending_list;
99 Eina_List *hidden_list;
100 Ecore_Timer *force_update_timer;
101 Ecore_Timer *pending_timer;
102 Eina_List *gbar_open_pending_list;
103 Ecore_Timer *gbar_open_pending_timer;
105 Eina_List *gbar_list;
107 int pending_timer_freezed;
108 int force_timer_freezed;
111 .force_update_list = NULL,
113 .pending_list = NULL,
115 .force_update_timer = NULL,
116 .pending_timer = NULL,
117 .gbar_open_pending_list = NULL,
118 .gbar_open_pending_timer = NULL,
119 .state = STATE_UNKNOWN,
122 .pending_timer_freezed = 0,
123 .force_timer_freezed = 0,
126 static Eina_Bool updator_cb(void *data);
127 static inline void update_monitor_del(const char *id, struct item *item);
128 static int append_force_update_list(struct item *item);
129 static void reset_widget_updated_flag(struct item *item);
130 static int append_pending_list(struct item *item);
132 static void pending_timer_freeze(void)
134 DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
135 if (!s_info.pending_timer) {
139 if (!s_info.pending_timer_freezed) {
140 DbgPrint("Freeze the pending timer\n");
141 ecore_timer_freeze(s_info.pending_timer);
144 s_info.pending_timer_freezed++;
147 static void pending_timer_thaw(void)
149 DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
150 if (!s_info.pending_timer_freezed) {
154 if (!s_info.pending_timer) {
155 s_info.pending_timer_freezed = 0;
159 s_info.pending_timer_freezed--;
160 if (!s_info.pending_timer_freezed) {
161 DbgPrint("Thaw the pending timer\n");
162 ecore_timer_thaw(s_info.pending_timer);
166 static void force_timer_freeze(void)
168 DbgPrint("Freeze force timer: %d\n", s_info.force_timer_freezed);
169 if (!s_info.force_update_timer) {
173 if (!s_info.force_timer_freezed) {
174 DbgPrint("Force timer freezed\n");
175 ecore_timer_freeze(s_info.force_update_timer);
178 s_info.force_timer_freezed++;
181 static void force_timer_thaw(void)
183 DbgPrint("Freezed force count: %d\n", s_info.force_timer_freezed);
184 if (!s_info.force_timer_freezed) {
188 if (!s_info.force_update_timer) {
189 s_info.force_timer_freezed = 0;
193 s_info.force_timer_freezed--;
194 if (!s_info.force_timer_freezed) {
195 DbgPrint("Thaw the force timer\n");
196 ecore_timer_thaw(s_info.force_update_timer);
201 * -1 : GBAR is opened, but not mine
202 * 0 : GBAR is not opened
203 * 1 : my GBAR is opened
205 static inline enum gbar_open_state gbar_is_opened(const char *pkgname)
209 struct instance *inst;
212 EINA_LIST_FOREACH(s_info.gbar_list, l, inst) {
213 if (pkgname && !strcmp(pkgname, inst->item->pkgname)) {
214 return GBAR_IS_OPENED;
220 return i > 0 ? GBAR_IS_OPENED_BUT_NOT_MINE : GBAR_IS_NOT_OPENED;
223 static Eina_Bool gbar_open_pended_cmd_consumer_cb(void *data)
227 item = eina_list_nth(s_info.gbar_open_pending_list, 0);
232 if (eina_list_data_find(s_info.update_list, item)) {
233 return ECORE_CALLBACK_RENEW;
236 s_info.gbar_open_pending_list = eina_list_remove(s_info.gbar_open_pending_list, item);
239 * To prevent from checking the is_updated function
241 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
242 /* Item is destroyed */
245 if (s_info.gbar_open_pending_list) {
246 return ECORE_CALLBACK_RENEW;
250 s_info.gbar_open_pending_timer = NULL;
251 return ECORE_CALLBACK_CANCEL;
254 static Eina_Bool update_timeout_cb(void *data)
260 ErrPrint("UPDATE TIMEOUT ========> %s - %s\n", item->inst->item->pkgname, item->inst->id);
262 if (!eina_list_data_find(s_info.update_list, item)) {
263 ErrPrint("Updating item is not matched\n");
266 fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
267 fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,timeout", NO_ALARM, DEFAULT_LIFE_TIMER);
268 s_info.update_list = eina_list_remove(s_info.update_list, item);
271 return ECORE_CALLBACK_CANCEL;
274 static inline void update_monitor_cnt(struct item *item)
279 now = util_timestamp();
280 interval = now - item->update_interval;
284 * If the content update is processed in too short time,
285 * don't increase the monitor counter, instead of it
286 * set the heavy updating flag.
287 * And handling this heavy updating from the
288 * file update callback.
290 if (interval >= MINIMUM_UPDATE_INTERVAL) {
291 if (eina_list_data_find(s_info.update_list, item)) {
294 * If already in updating mode,
295 * reset the monitor_cnt to 1,
296 * all updated event will be merged into A inotify event
298 DbgPrint("While waiting updated event, content is updated [%s]\n", item->inst->id);
299 item->monitor_cnt = 1;
304 item->heavy_updating = 1;
307 item->update_interval = now;
310 static inline void do_force_update(struct item *item)
314 if (item->monitor) { /*!< If this item is already in update process */
318 if (!IS_WIDGET_SHOWN(item)) {
319 DbgPrint("%s is not shown yet. it will be added to normal pending list\n", item->inst->item->pkgname);
320 (void)append_force_update_list(item);
324 if (item->state != STATE_RESUMED) {
325 DbgPrint("Item is paused. but it will be updated forcely(%s)\n", item->inst->item->pkgname);
328 item->updated_in_pause = 0;
330 ret = so_is_updated(item->inst);
332 if (so_need_to_destroy(item->inst) == WIDGET_NEED_TO_DESTROY) {
333 widget_provider_send_deleted(item->inst->item->pkgname, item->inst->id);
334 widget_destroy(item->inst->item->pkgname, item->inst->id, WIDGET_DESTROY_TYPE_DEFAULT);
337 * Every caller of this, must not access the item from now.
342 reset_widget_updated_flag(item);
348 * Check the update_list, if you want make serialized update
350 if (/*s_info.update_list || */gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED_BUT_NOT_MINE) {
351 DbgPrint("%s is busy, migrate to normal pending list\n", item->inst->id);
352 (void)append_pending_list(item);
356 item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
357 if (!item->monitor) {
358 ErrPrint("Failed to add update monitor %s(%s):%d\n",
359 item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
363 ret = so_update(item->inst);
365 ecore_timer_del(item->monitor);
366 item->monitor = NULL;
367 reset_widget_updated_flag(item);
373 * Counter of the event monitor is only used for asynchronous content updating,
374 * So reset it to 1 from here because the async updating is started now,
375 * even if it is accumulated by other event function before this.
377 item->monitor_cnt = 1;
381 * While waiting the Callback function call,
382 * Add this for finding the crash
384 fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
386 if (ret & WIDGET_NEED_TO_SCHEDULE) {
387 (void)append_pending_list(item);
390 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
391 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", item->inst->item->pkgname);
392 (void)append_force_update_list(item);
395 if (ret & WIDGET_OUTPUT_UPDATED) {
398 * In this case, there is potential issue
399 * 1. User added update CALLBACK -> Inotify event (Only once)
400 * > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
401 * 2. Inotify event -> User added update CALLBACK -> Inotify event
402 * > Okay. What we want is this.
404 update_monitor_cnt(item);
409 * This should be updated after "update_monitor_cnt" function call,
410 * because the update_monitor_cnt function will see the s_info.update variable,
412 s_info.update_list = eina_list_append(s_info.update_list, item);
417 static Eina_Bool force_update_cb(void *data)
421 item = eina_list_nth(s_info.force_update_list, 0);
426 s_info.force_update_list = eina_list_remove(s_info.force_update_list, item);
428 do_force_update(item);
430 if (s_info.force_update_list) {
431 return ECORE_CALLBACK_RENEW;
435 s_info.force_update_timer = NULL;
436 return ECORE_CALLBACK_CANCEL;
439 static inline __attribute__((always_inline)) int activate_force_update_consumer(void)
441 if (s_info.force_update_timer) {
442 return WIDGET_ERROR_NONE;
445 s_info.force_update_timer = ecore_timer_add(0.000001f, force_update_cb, NULL);
446 if (!s_info.force_update_timer) {
447 ErrPrint("Failed to add a new force update timer\n");
448 return WIDGET_ERROR_FAULT;
451 DbgPrint("Force update timer is registered\n");
453 return WIDGET_ERROR_NONE;
456 static inline void deactivate_force_update_consumer(void)
458 if (!s_info.force_update_timer) {
462 ecore_timer_del(s_info.force_update_timer);
463 s_info.force_update_timer = NULL;
465 DbgPrint("Force update timer is deleted\n");
468 static Eina_Bool pended_cmd_consumer_cb(void *data)
472 item = eina_list_nth(s_info.pending_list, 0);
477 if (eina_list_data_find(s_info.update_list, item) || gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED_BUT_NOT_MINE) {
478 return ECORE_CALLBACK_RENEW;
481 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
484 * To prevent from checking the is_updated function
486 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
487 /* item is destroyed */
490 if (s_info.pending_list) {
491 return ECORE_CALLBACK_RENEW;
495 s_info.pending_timer = NULL;
496 s_info.pending_timer_freezed = 0;
497 return ECORE_CALLBACK_CANCEL;
500 static inline __attribute__((always_inline)) int activate_pending_consumer(void)
502 if (s_info.pending_timer) {
503 return WIDGET_ERROR_NONE;
506 s_info.pending_timer = ecore_timer_add(0.000001f, pended_cmd_consumer_cb, NULL);
507 if (!s_info.pending_timer) {
508 ErrPrint("Failed to add a new pended command consumer\n");
509 return WIDGET_ERROR_FAULT;
513 * Do not increase the freezed counter.
514 * Just freeze the timer.
516 if (s_info.pending_timer_freezed) {
517 ecore_timer_freeze(s_info.pending_timer);
520 return WIDGET_ERROR_NONE;
523 static inline void deactivate_pending_consumer(void)
525 if (!s_info.pending_timer) {
529 ecore_timer_del(s_info.pending_timer);
530 s_info.pending_timer = NULL;
531 s_info.pending_timer_freezed = 0;
534 static inline void deactivate_gbar_open_pending_consumer(void)
536 if (!s_info.gbar_open_pending_timer) {
540 ecore_timer_del(s_info.gbar_open_pending_timer);
541 s_info.gbar_open_pending_timer = NULL;
544 static inline int __attribute__((always_inline)) activate_gbar_open_pending_consumer(void)
546 if (s_info.gbar_open_pending_timer) {
550 s_info.gbar_open_pending_timer = ecore_timer_add(0.000001f, gbar_open_pended_cmd_consumer_cb, NULL);
551 if (!s_info.gbar_open_pending_timer) {
552 ErrPrint("Failed to add a new pended command consumer\n");
553 return WIDGET_ERROR_FAULT;
559 static inline void migrate_to_gbar_open_pending_list(const char *pkgname)
566 EINA_LIST_FOREACH_SAFE(s_info.pending_list, l, n, item) {
567 if (strcmp(pkgname, item->inst->item->pkgname)) {
571 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
572 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
577 * These items will be moved to the pending list after the GBAR is closed.
578 * Force list -> pd open list -> pending list.
579 * So there is no way to go back to the foce update list again.
582 * the ITEM must only exists in one list, pending list or force_update_list
583 * It is not accepted to exists in two list at same time.
585 EINA_LIST_FOREACH_SAFE(s_info.force_update_list, l, n, item) {
586 if (strcmp(pkgname, item->inst->item->pkgname)) {
590 s_info.force_update_list = eina_list_remove(s_info.force_update_list, item);
591 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
595 if (s_info.gbar_open_pending_list) {
596 activate_gbar_open_pending_consumer();
599 if (!s_info.pending_list) {
600 deactivate_pending_consumer();
603 if (!s_info.force_update_list) {
604 deactivate_force_update_consumer();
608 static inline void migrate_to_pending_list(const char *pkgname)
615 EINA_LIST_FOREACH_SAFE(s_info.gbar_open_pending_list, l, n, item) {
616 if (strcmp(pkgname, item->inst->item->pkgname)) {
620 s_info.gbar_open_pending_list = eina_list_remove(s_info.gbar_open_pending_list, item);
621 s_info.pending_list = eina_list_append(s_info.pending_list, item);
625 if (s_info.pending_list) {
626 activate_pending_consumer();
629 if (!s_info.gbar_open_pending_list) {
630 deactivate_gbar_open_pending_consumer();
634 static inline int is_pended_item(struct item *item)
636 struct item *in_item;
637 if (gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED) {
638 in_item = eina_list_data_find(s_info.gbar_open_pending_list, item);
640 in_item = eina_list_data_find(s_info.pending_list, item);
643 return (in_item == item);
646 static int append_pending_list(struct item *item)
648 if (item->deleteme) {
649 DbgPrint("Item will be deleted, ignore update request: %s\n", item->inst->id);
650 return WIDGET_ERROR_RESOURCE_BUSY;
653 if (eina_list_data_find(s_info.force_update_list, item)) {
654 DbgPrint("Already exists in force list\n");
655 return WIDGET_ERROR_NONE;
658 if (gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED) {
659 if (eina_list_data_find(s_info.gbar_open_pending_list, item) == item) {
660 DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
661 return WIDGET_ERROR_ALREADY_EXIST;
664 if (activate_gbar_open_pending_consumer() < 0) {
665 ErrPrint("Failed to activate GBAR open pending consumer\n");
666 return WIDGET_ERROR_FAULT;
669 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
671 if (eina_list_data_find(s_info.pending_list, item) == item) {
672 DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
673 return WIDGET_ERROR_ALREADY_EXIST;
676 if (IS_WIDGET_SHOWN(item)) {
677 if (activate_pending_consumer() < 0) {
678 return WIDGET_ERROR_FAULT;
681 s_info.pending_list = eina_list_append(s_info.pending_list, item);
683 if (eina_list_data_find(s_info.hidden_list, item) == item) {
684 DbgPrint("Already in hidden list - %s\n", item->inst->item->pkgname);
685 return WIDGET_ERROR_ALREADY_EXIST;
688 s_info.hidden_list = eina_list_append(s_info.hidden_list, item);
692 return WIDGET_ERROR_NONE;
695 static inline int clear_from_pending_list(struct item *item)
700 EINA_LIST_FOREACH(s_info.pending_list, l, tmp) {
705 s_info.pending_list = eina_list_remove_list(s_info.pending_list, l);
706 if (!s_info.pending_list) {
707 deactivate_pending_consumer();
709 return WIDGET_ERROR_NONE;
712 return WIDGET_ERROR_NOT_EXIST;
715 static int append_force_update_list(struct item *item)
717 if (item->deleteme) {
718 DbgPrint("Item will be deleted, ignore force update request: %s\n", item->inst->id);
719 return WIDGET_ERROR_RESOURCE_BUSY;
723 * If the item is already in pending list, remove it.
725 clear_from_pending_list(item);
727 if (gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED) {
728 if (eina_list_data_find(s_info.gbar_open_pending_list, item) == item) {
729 DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
730 return WIDGET_ERROR_ALREADY_EXIST;
733 if (activate_gbar_open_pending_consumer() < 0) {
734 ErrPrint("Failed to activate GBAR open pending consumer\n");
735 return WIDGET_ERROR_FAULT;
738 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
740 if (eina_list_data_find(s_info.force_update_list, item)) {
741 DbgPrint("Already in force update list\n");
742 return WIDGET_ERROR_NONE;
745 if (IS_WIDGET_SHOWN(item)) {
746 if (activate_force_update_consumer() < 0) {
747 return WIDGET_ERROR_FAULT;
750 s_info.force_update_list = eina_list_append(s_info.force_update_list, item);
752 if (eina_list_data_find(s_info.hidden_list, item) == item) {
753 DbgPrint("Already in hidden list - %s\n", item->inst->id);
754 return WIDGET_ERROR_ALREADY_EXIST;
757 s_info.hidden_list = eina_list_append(s_info.hidden_list, item);
759 DbgPrint("forced item is moved to hidden_list - %s\n", item->inst->id);
763 return WIDGET_ERROR_NONE;
766 static inline int clear_from_force_update_list(struct item *item)
771 EINA_LIST_FOREACH(s_info.force_update_list, l, tmp) {
776 s_info.force_update_list = eina_list_remove_list(s_info.force_update_list, l);
777 if (!s_info.force_update_list) {
778 deactivate_force_update_consumer();
781 return WIDGET_ERROR_NONE;
784 return WIDGET_ERROR_NOT_EXIST;
787 static inline void migrate_to_pending_list_from_hidden_list(struct item *item)
789 if (!eina_list_data_find(s_info.hidden_list, item)) {
793 s_info.hidden_list = eina_list_remove(s_info.hidden_list, item);
794 append_pending_list(item);
799 * This function can call the update callback
800 * return 0 if there is no changes
801 * return -1 the item is deleted
803 static inline int timer_thaw(struct item *item)
814 ecore_timer_thaw(item->timer);
815 period = ecore_timer_interval_get(item->timer);
816 pending = ecore_timer_pending_get(item->timer);
817 delay = util_time_delay_for_compensation(period) - pending;
818 ecore_timer_delay(item->timer, delay);
820 if (item->sleep_at == 0.0f) {
824 sleep_time = util_timestamp() - item->sleep_at;
825 item->sleep_at = 0.0f;
827 if (sleep_time > pending) {
830 * Before do updating forcely, clear it from the pending list.
831 * We will consume it from here now.
833 (void)clear_from_pending_list(item);
835 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
836 /* item is destroyed */
837 return UPDATE_ITEM_DELETED;
839 return UPDATE_INVOKED;
843 return UPDATE_NOT_INVOKED;
846 static void timer_freeze(struct item *item)
852 ecore_timer_freeze(item->timer);
854 if (ecore_timer_interval_get(item->timer) <= 1.0f) {
858 #if defined(_USE_ECORE_TIME_GET)
859 item->sleep_at = ecore_time_get();
862 if (gettimeofday(&tv, NULL) < 0) {
863 ErrPrint("gettimeofday: %d\n", errno);
868 item->sleep_at = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
872 static inline Eina_List *find_item(struct instance *inst)
877 EINA_LIST_FOREACH(s_info.item_list, l, item) {
878 if (item->inst == inst) {
886 static int desc_updated_cb(const char *filename, void *data, int over)
891 WarnPrint("Event Q overflow\n");
896 DbgPrint("DESC %s is updated\n", filename);
897 if (item->is_gbar_show) {
898 widget_damage_region_s region = {
905 widget_provider_send_updated(item->inst->item->pkgname, item->inst->id, WIDGET_PRIMARY_BUFFER, ®ion, 1, filename);
907 ErrPrint("But GBAR is not opened, Ignore this update (%s)\n", item->inst->id);
912 static inline int output_handler(struct item *item)
917 if (item->monitor_cnt < 0 || item->heavy_updating) {
918 if (!item->heavy_updating) {
919 WarnPrint("%s has invalid monitor_cnt\n", item->inst->id);
922 item->heavy_updating = 0; /* Reset flag */
925 item->monitor_cnt = 0;
928 if (item->monitor_cnt == 0) {
930 fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
934 ecore_timer_del(item->monitor);
935 item->monitor = NULL;
938 s_info.update_list = eina_list_remove(s_info.update_list, item);
940 if (item->deleteme) {
941 update_monitor_del(item->inst->id, item);
942 widget_provider_send_deleted(item->inst->item->pkgname, item->inst->id);
943 (void)so_destroy(item->inst, item->unload_so);
952 static int file_updated_cb(const char *filename, void *data, int over)
958 char *content = NULL;
965 WarnPrint("Event Q overflow\n");
970 if (item->deleteme) {
971 DbgPrint("Item is in deleting process. (%s)\n", filename);
975 ESTIMATE_START(item->inst->id);
977 ret = util_get_filesize(filename);
979 ErrPrint("Content is updated. but invalid. ret = %d (Update is ignored)\n", ret);
980 ESTIMATE_END(item->inst->id);
981 return EXIT_SUCCESS; /*!< To keep the callback */
984 ret = so_get_output_info(item->inst, &w, &h, &priority, &content, &title);
986 ErrPrint("widget_get_info returns %d\n", ret);
987 ESTIMATE_END(item->inst->id);
988 return EXIT_SUCCESS; /*!< To keep the callback */
992 * Alternative information can be NOT_IMPLEMENTED
993 * And we can ignore its error.
995 ret = so_get_alt_info(item->inst, &icon, &name);
997 ErrPrint("widget_get_alt_info returns %d (ignored)\n", ret);
1000 if (IS_WIDGET_SHOWN(item)) {
1001 widget_damage_region_s region = {
1008 * If the content is not written on shared buffer (pixmap, shm, raw file, ...)
1009 * We cannot use the direct path for sending updated event.
1011 widget_provider_send_extra_info(item->inst->item->pkgname, item->inst->id, item->inst->priority,
1012 content, title, item->inst->icon, item->inst->name);
1013 widget_provider_send_updated(item->inst->item->pkgname, item->inst->id, WIDGET_PRIMARY_BUFFER, ®ion, 0, NULL);
1015 item->is_widget_updated++;
1018 ESTIMATE_END(item->inst->id);
1020 return output_handler(item);
1023 static void reset_widget_updated_flag(struct item *item)
1025 widget_damage_region_s region = {
1032 if (!item->is_widget_updated) {
1036 DbgPrint("[%s] Updated %d times, (content: %s), (title: %s)\n",
1037 item->inst->id, item->is_widget_updated,
1038 item->inst->content, item->inst->title);
1041 * If the content is not written on shared buffer (pixmap, shm, raw file, ...)
1042 * We cannot use the direct path for sending updated event.
1044 widget_provider_send_extra_info(item->inst->item->pkgname, item->inst->id, item->inst->priority,
1045 item->inst->content, item->inst->title, item->inst->icon, item->inst->name);
1046 widget_provider_send_updated(item->inst->item->pkgname, item->inst->id, WIDGET_PRIMARY_BUFFER, ®ion, 0, NULL);
1048 item->is_widget_updated = 0;
1051 static inline int clear_from_gbar_open_pending_list(struct item *item)
1056 EINA_LIST_FOREACH(s_info.gbar_open_pending_list, l, tmp) {
1061 s_info.gbar_open_pending_list = eina_list_remove_list(s_info.gbar_open_pending_list, l);
1062 if (!s_info.gbar_open_pending_list) {
1063 deactivate_gbar_open_pending_consumer();
1065 return WIDGET_ERROR_NONE;
1068 return WIDGET_ERROR_NOT_EXIST;
1073 * This must has to return ECORE_CALLBACK_CANCEL, only if the item is deleted.
1074 * So every caller, should manage the deleted item correctly.
1076 static Eina_Bool updator_cb(void *data)
1083 if (item->monitor) { /*!< If this item is already in update process */
1084 return ECORE_CALLBACK_RENEW;
1087 if (!IS_WIDGET_SHOWN(item)) {
1088 DbgPrint("%s is not shown yet. make delay for updates\n", item->inst->item->pkgname);
1089 (void)append_pending_list(item);
1090 return ECORE_CALLBACK_RENEW;
1093 if (item->state != STATE_RESUMED) {
1094 item->updated_in_pause++;
1095 DbgPrint("%s is paused[%d]. make delay for updating\n", item->inst->item->pkgname, item->updated_in_pause);
1096 return ECORE_CALLBACK_RENEW;
1099 item->updated_in_pause = 0;
1101 ret = so_is_updated(item->inst);
1103 if (so_need_to_destroy(item->inst) == WIDGET_NEED_TO_DESTROY) {
1104 widget_provider_send_deleted(item->inst->item->pkgname, item->inst->id);
1105 widget_destroy(item->inst->item->pkgname, item->inst->id, WIDGET_DESTROY_TYPE_DEFAULT);
1108 * Every caller of this, must not access the item from now.
1110 return ECORE_CALLBACK_CANCEL;
1113 reset_widget_updated_flag(item);
1114 return ECORE_CALLBACK_RENEW;
1119 * Check the update_list, if you want make serialized update
1121 if (/*s_info.update_list || */gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED_BUT_NOT_MINE) {
1122 DbgPrint("%s is busy\n", item->inst->id);
1123 (void)append_pending_list(item);
1124 return ECORE_CALLBACK_RENEW;
1127 item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
1128 if (!item->monitor) {
1129 ErrPrint("Failed to add update monitor %s(%s):%d\n",
1130 item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
1131 return ECORE_CALLBACK_RENEW;
1134 ret = so_update(item->inst);
1136 ecore_timer_del(item->monitor);
1137 item->monitor = NULL;
1138 reset_widget_updated_flag(item);
1139 return ECORE_CALLBACK_RENEW;
1144 * Counter of the event monitor is only used for asynchronous content updating,
1145 * So reset it to 1 from here because the async updating is started now,
1146 * even if it is accumulated by other event function before this.
1148 item->monitor_cnt = 1;
1152 * While waiting the Callback function call,
1153 * Add this for finding the crash
1155 fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
1157 if (ret & WIDGET_NEED_TO_SCHEDULE) {
1158 (void)append_pending_list(item);
1161 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
1162 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", item->inst->item->pkgname);
1163 (void)append_force_update_list(item);
1166 if (ret & WIDGET_OUTPUT_UPDATED) {
1169 * In this case, there is potential issue
1170 * 1. User added update CALLBACK -> Inotify event (Only once)
1171 * > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
1172 * 2. Inotify event -> User added update CALLBACK -> Inotify event
1173 * > Okay. What we want is this.
1175 update_monitor_cnt(item);
1180 * This should be updated after "update_monitor_cnt" function call,
1181 * because the update_monitor_cnt function will see the s_info.update variable,
1183 s_info.update_list = eina_list_append(s_info.update_list, item);
1185 return ECORE_CALLBACK_RENEW;
1188 static inline void update_monitor_del(const char *id, struct item *item)
1193 tmp = (char *)util_uri_to_path(id);
1195 ErrPrint("Invalid parameter\n");
1199 update_monitor_del_update_cb(tmp, file_updated_cb);
1201 len = strlen(tmp) + strlen(".desc") + 1;
1204 ErrPrint("malloc: %d (%s.desc)\n", errno, util_uri_to_path(id));
1208 snprintf(tmp, len, "%s.desc", util_uri_to_path(id));
1209 update_monitor_del_update_cb(tmp, desc_updated_cb);
1213 static inline int add_desc_update_monitor(const char *id, struct item *item)
1219 len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
1220 filename = malloc(len);
1222 ErrPrint("malloc: %d (%s.desc)\n", errno, util_uri_to_path(id));
1223 return WIDGET_ERROR_OUT_OF_MEMORY;
1226 snprintf(filename, len, "%s.desc", util_uri_to_path(id));
1227 ret = update_monitor_add_update_cb(filename, desc_updated_cb, item);
1232 static inline int add_file_update_monitor(const char *id, struct item *item)
1234 return update_monitor_add_update_cb(util_uri_to_path(id), file_updated_cb, item);
1237 static inline int update_monitor_add(const char *id, struct item *item)
1241 * item->inst is not available yet.
1243 add_file_update_monitor(id, item);
1244 add_desc_update_monitor(id, item);
1245 return WIDGET_ERROR_NONE;
1248 static int disconnected_cb(int handle, void *data)
1254 struct connection *connection;
1255 struct connection *conn_handle;
1257 connection = connection_find_by_fd(handle);
1262 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1263 EINA_LIST_FOREACH_SAFE(item->direct_path_list, k, n, conn_handle) {
1264 if (conn_handle == connection) {
1265 item->direct_path_list = eina_list_remove(item->direct_path_list, conn_handle);
1266 (void)connection_unref(conn_handle);
1274 HAPI void widget_viewer_init(void)
1277 ret = connection_add_event_handler(CONNECTION_EVENT_TYPE_DISCONNECTED, disconnected_cb, NULL);
1279 ErrPrint("Unable to add an event handler\n");
1284 HAPI void widget_viewer_fini(void)
1288 ret = widget_delete_all_deleteme();
1290 DbgPrint("Delete all deleteme: %d\n", ret);
1293 ret = widget_delete_all();
1295 DbgPrint("Delete all: %d\n", ret);
1298 /* Just for in case of ... */
1299 deactivate_pending_consumer();
1300 deactivate_gbar_open_pending_consumer();
1302 eina_list_free(s_info.gbar_open_pending_list);
1303 s_info.gbar_open_pending_list = NULL;
1304 eina_list_free(s_info.pending_list);
1305 s_info.pending_list = NULL;
1307 (void)connection_del_event_handler(CONNECTION_EVENT_TYPE_DISCONNECTED, disconnected_cb);
1313 * Exported API for each widgetes.
1315 int widget_send_updated(const char *pkgname, const char *id, int idx, int x, int y, int w, int h, int gbar, const char *descfile)
1319 int ret = WIDGET_ERROR_NOT_EXIST;
1320 widget_damage_region_s region = {
1327 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1328 if (strcmp(item->inst->item->pkgname, pkgname) || strcmp(item->inst->id, id)) {
1332 if (item->direct_path_list) {
1334 struct connection *conn_handle;
1335 EINA_LIST_FOREACH(item->direct_path_list, l, conn_handle) {
1336 ret = widget_provider_send_direct_updated(connection_handle(conn_handle), pkgname, id, idx, ®ion, gbar, descfile);
1339 ret = widget_provider_send_updated(pkgname, id, idx, ®ion, gbar, descfile);
1348 int widget_send_buffer_updated(const char *pkgname, const char *id, widget_buffer_h handle, int idx, int x, int y, int w, int h, int gbar, const char *descfile)
1352 int ret = WIDGET_ERROR_NOT_EXIST;
1353 widget_damage_region_s region = {
1360 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1361 if (strcmp(item->inst->item->pkgname, pkgname) || strcmp(item->inst->id, id)) {
1365 if (item->direct_path_list) {
1367 struct connection *conn_handle;
1368 EINA_LIST_FOREACH(item->direct_path_list, l, conn_handle) {
1369 ret = widget_provider_send_direct_buffer_updated(connection_handle(conn_handle), handle, idx, ®ion, gbar, descfile);
1372 ret = widget_provider_send_buffer_updated(handle, idx, ®ion, gbar, descfile);
1381 const char *widget_find_pkgname(const char *filename)
1386 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1387 if (!strcmp(item->inst->id, filename)) {
1388 return item->inst->item->pkgname;
1395 int widget_update_extra_info(const char *id, const char *content, const char *title, const char *icon, const char *name)
1400 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1401 if (!strcmp(item->inst->id, id)) {
1402 if (content && strlen(content)) {
1405 _content = strdup(content);
1407 if (item->inst->content) {
1408 free(item->inst->content);
1409 item->inst->content = NULL;
1412 item->inst->content = _content;
1414 ErrPrint("strdup: %d\n", errno);
1418 if (title && strlen(title)) {
1421 _title = strdup(title);
1423 if (item->inst->title) {
1424 free(item->inst->title);
1425 item->inst->title = NULL;
1428 item->inst->title = _title;
1430 ErrPrint("strdup: %d\n", errno);
1434 if (icon && strlen(icon)) {
1437 _icon = strdup(icon);
1439 if (item->inst->icon) {
1440 free(item->inst->icon);
1441 item->inst->icon = NULL;
1444 item->inst->icon = _icon;
1446 ErrPrint("strdup: %d\n", errno);
1450 if (name && strlen(name)) {
1453 _name = strdup(name);
1455 if (item->inst->name) {
1456 free(item->inst->name);
1457 item->inst->name = NULL;
1460 item->inst->name = _name;
1462 ErrPrint("strdup: %d\n", errno);
1466 return WIDGET_ERROR_NONE;
1470 return WIDGET_ERROR_NOT_EXIST;
1473 int widget_request_update_by_id(const char *filename)
1478 if (so_current_op() != WIDGET_OP_UNKNOWN) {
1479 ErrPrint("Current operation: %d\n", so_current_op());
1482 * Some case requires to update the content of other widget from widget_XXX ABI.
1483 * In that case this function can be used so we have not to filter it from here.
1484 * ex) Setting accessibility.
1485 * Press the assistive light, turned on, need to update other instances too.
1486 * Then the widget will use this function from widget_clicked function.
1490 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1491 if (!strcmp(item->inst->id, filename)) {
1492 return append_pending_list(item);
1496 return WIDGET_ERROR_NOT_EXIST;
1499 int widget_trigger_update_monitor(const char *filename, int is_gbar)
1504 if (so_current_op() != WIDGET_OP_UNKNOWN) {
1505 ErrPrint("Current operation: %d\n", so_current_op());
1506 return WIDGET_ERROR_INVALID_PARAMETER;
1511 len = strlen(filename) + strlen(".desc");
1513 fname = malloc(len + 1);
1515 ErrPrint("malloc: %d\n", errno);
1516 return WIDGET_ERROR_OUT_OF_MEMORY;
1519 snprintf(fname, len, "%s.desc", filename);
1521 fname = strdup(filename);
1523 ErrPrint("strdup: %d\n", errno);
1524 return WIDGET_ERROR_OUT_OF_MEMORY;
1528 if (access(fname, R_OK | W_OK) != 0) {
1529 ErrPrint("access: %s (%d)\n", fname, errno);
1530 ret = WIDGET_ERROR_IO_ERROR;
1532 ret = update_monitor_trigger_update_cb(fname, 0);
1539 HAPI int widget_open_gbar(const char *pkgname, const char *id)
1541 struct instance *inst;
1542 struct instance *tmp;
1545 inst = so_find_instance(pkgname, id);
1547 ErrPrint("Instance is not found\n");
1548 return WIDGET_ERROR_NOT_EXIST;
1551 EINA_LIST_FOREACH(s_info.gbar_list, l, tmp) {
1557 if (!s_info.gbar_list) {
1558 pending_timer_freeze();
1562 * Freeze the force timer only in this case.
1564 force_timer_freeze();
1567 s_info.gbar_list = eina_list_append(s_info.gbar_list, inst);
1570 * Find all instances from the pending list.
1571 * Move them to gbar_open_pending_timer
1573 migrate_to_gbar_open_pending_list(pkgname);
1574 return WIDGET_ERROR_NONE;
1577 HAPI int widget_close_gbar(const char *pkgname, const char *id)
1581 struct instance *tmp;
1582 struct instance *inst;
1584 inst = so_find_instance(pkgname, id);
1586 ErrPrint("Insatnce is not found\n");
1587 return WIDGET_ERROR_NOT_EXIST;
1590 EINA_LIST_FOREACH_SAFE(s_info.gbar_list, l, n, tmp) {
1595 s_info.gbar_list = eina_list_remove(s_info.gbar_list, tmp);
1596 if (!s_info.gbar_list) {
1597 pending_timer_thaw();
1602 * Move all items in gbar_open_pending_list
1605 migrate_to_pending_list(pkgname);
1606 return WIDGET_ERROR_NONE;
1609 return WIDGET_ERROR_NOT_EXIST;
1612 static struct method s_table[] = {
1619 HAPI int widget_create(const char *pkgname, const char *id, struct widget_create_arg *arg, int *w, int *h, double *priority, char **content, char **title)
1621 struct instance *inst;
1631 inst = so_find_instance(pkgname, id);
1633 DbgPrint("Instance is already exists [%s - %s] content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, arg->content, arg->cluster, arg->category, arg->abi);
1634 return WIDGET_ERROR_NONE;
1637 if (!arg->skip_need_to_create) {
1638 ret = so_create_needed(pkgname, arg->cluster, arg->category, arg->abi);
1639 if (ret != WIDGET_NEED_TO_CREATE) {
1640 return WIDGET_ERROR_PERMISSION_DENIED;
1646 item = calloc(1, sizeof(*item));
1648 ErrPrint("calloc: %d (%s - %s, content[%s], cluster[%s], category[%s], abi[%s])\n", errno, pkgname, id, arg->content, arg->cluster, arg->category, arg->abi);
1649 return WIDGET_ERROR_OUT_OF_MEMORY;
1652 ret = update_monitor_add(id, item);
1658 if (arg->direct_addr) {
1659 struct connection *conn_handle;
1661 conn_handle = connection_find_by_addr(arg->direct_addr);
1663 conn_handle = connection_create(arg->direct_addr, (void *)s_table);
1665 ErrPrint("Direct update-path is not supported\n");
1667 DbgPrint("Direct update-path is created: %s\n", id);
1668 item->direct_path_list = eina_list_append(item->direct_path_list, conn_handle);
1671 item->direct_path_list = eina_list_append(item->direct_path_list, connection_ref(conn_handle));
1672 DbgPrint("Direct update-path is referred: %s\n", id);
1676 create_ret = so_create(pkgname, id, arg->content, arg->timeout, arg->has_widget_script, arg->cluster, arg->category, arg->abi, &inst);
1677 if (create_ret < 0) {
1678 struct connection *conn_handle;
1680 update_monitor_del(id, item);
1681 EINA_LIST_FREE(item->direct_path_list, conn_handle) {
1682 (void)connection_unref(conn_handle);
1693 item->state = STATE_UNKNOWN;
1695 if (arg->period > 0.0f && !s_info.secured) {
1696 item->timer = util_timer_add(arg->period, updator_cb, item);
1698 struct connection *conn_handle;
1699 ErrPrint("Failed to add timer (%s - %s, content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, arg->content, arg->cluster, arg->category, arg->abi);
1700 update_monitor_del(id, item);
1701 EINA_LIST_FREE(item->direct_path_list, conn_handle) {
1702 (void)connection_unref(conn_handle);
1704 (void)so_destroy(inst, item->unload_so);
1706 return WIDGET_ERROR_FAULT;
1709 if (s_info.state == STATE_PAUSED) {
1713 DbgPrint("Local update timer is disabled: %lf (%d)\n", arg->period, s_info.secured);
1717 s_info.item_list = eina_list_append(s_info.item_list, item);
1719 if (create_ret & WIDGET_NEED_TO_SCHEDULE) {
1720 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
1721 (void)append_pending_list(item);
1724 if (create_ret & WIDGET_FORCE_TO_SCHEDULE) {
1725 DbgPrint("%s Returns WIDGET_NEED_TO_FORCE_UPDATE\n", pkgname);
1726 (void)append_force_update_list(item);
1729 if (create_ret & WIDGET_OUTPUT_UPDATED) {
1730 update_monitor_cnt(item);
1733 * To send a output info, get the info forcely.
1734 * but the output file monitor will do this again
1736 * This function will set the tmp_content and tmp_title
1737 * even if it has no updates on the content, title,
1738 * it will set them to NULL.
1740 if (so_get_output_info(inst, w, h, priority, content, title) == (int)WIDGET_ERROR_NONE) {
1744 tmp = strdup(*content);
1746 ErrPrint("strdup: %d\n", errno);
1755 tmp = strdup(*title);
1757 ErrPrint("strdup: %d\n", errno);
1767 *priority = inst->priority;
1768 return need_to_create;
1771 HAPI int widget_destroy(const char *pkgname, const char *id, int type)
1775 struct instance *inst;
1776 struct instance *tmp;
1778 struct connection *conn_handle;
1780 inst = so_find_instance(pkgname, id);
1782 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1783 return WIDGET_ERROR_INVALID_PARAMETER;
1786 EINA_LIST_FOREACH_SAFE(s_info.gbar_list, l, n, tmp) {
1791 s_info.gbar_list = eina_list_remove(s_info.gbar_list, tmp);
1792 if (!s_info.gbar_list) {
1793 pending_timer_thaw();
1798 * Move all items in gbar_open_pending_list
1801 migrate_to_pending_list(pkgname);
1805 l = find_item(inst);
1807 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1808 return WIDGET_ERROR_NOT_EXIST;
1811 item = eina_list_data_get(l);
1812 s_info.item_list = eina_list_remove_list(s_info.item_list, l);
1814 s_info.update_list = eina_list_remove(s_info.update_list, item);
1815 s_info.hidden_list = eina_list_remove(s_info.hidden_list, item);
1816 clear_from_gbar_open_pending_list(item);
1817 clear_from_pending_list(item);
1818 clear_from_force_update_list(item);
1819 EINA_LIST_FREE(item->direct_path_list, conn_handle) {
1820 (void)connection_unref(conn_handle);
1824 ecore_timer_del(item->timer);
1829 * To keep the previous status, we should or'ing the value.
1831 item->unload_so = (item->unload_so || (type == WIDGET_DESTROY_TYPE_UNINSTALL) || (type == WIDGET_DESTROY_TYPE_UPGRADE));
1833 if (item->monitor) {
1836 update_monitor_del(id, item);
1837 (void)so_destroy(inst, item->unload_so);
1841 return WIDGET_ERROR_NONE;
1844 HAPI int widget_viewer_resize_widget(const char *pkgname, const char *id, int w, int h)
1847 struct instance *inst;
1851 inst = so_find_instance(pkgname, id);
1853 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
1854 return WIDGET_ERROR_INVALID_PARAMETER;
1857 l = find_item(inst);
1859 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
1860 return WIDGET_ERROR_NOT_EXIST;
1863 item = eina_list_data_get(l);
1866 ret = so_resize(inst, w, h);
1872 if (ret & WIDGET_NEED_TO_SCHEDULE) {
1873 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
1874 (void)append_pending_list(item);
1877 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
1878 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
1879 (void)append_force_update_list(item);
1882 if (ret & WIDGET_OUTPUT_UPDATED) {
1883 update_monitor_cnt(item);
1886 return WIDGET_ERROR_NONE;
1889 HAPI char *widget_pinup(const char *pkgname, const char *id, int pinup)
1891 struct instance *inst;
1894 inst = so_find_instance(pkgname, id);
1896 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1900 ret = so_pinup(inst, pinup);
1904 HAPI int widget_viewer_set_period(const char *pkgname, const char *id, double period)
1907 struct instance *inst;
1910 inst = so_find_instance(pkgname, id);
1912 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1913 return WIDGET_ERROR_INVALID_PARAMETER;
1916 l = find_item(inst);
1918 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1919 return WIDGET_ERROR_NOT_EXIST;
1922 item = eina_list_data_get(l);
1924 if (period <= 0.0f) {
1926 ecore_timer_del(item->timer);
1931 util_timer_interval_set(item->timer, period);
1932 } else if (!s_info.secured) {
1933 item->timer = util_timer_add(period, updator_cb, item);
1935 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1936 return WIDGET_ERROR_FAULT;
1939 if (s_info.state == STATE_PAUSED) {
1945 return WIDGET_ERROR_NONE;
1948 HAPI int widget_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1951 struct instance *inst;
1955 inst = so_find_instance(pkgname, id);
1957 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1958 return WIDGET_ERROR_INVALID_PARAMETER;
1961 l = find_item(inst);
1963 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1964 return WIDGET_ERROR_NOT_EXIST;
1967 item = eina_list_data_get(l);
1970 ret = so_clicked(inst, event, timestamp, x, y);
1976 if (ret & WIDGET_NEED_TO_SCHEDULE) {
1977 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
1978 (void)append_pending_list(item);
1981 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
1982 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
1983 (void)append_force_update_list(item);
1986 if (ret & WIDGET_OUTPUT_UPDATED) {
1987 update_monitor_cnt(item);
1990 return WIDGET_ERROR_NONE;
1993 HAPI int widget_script_event(const char *pkgname, const char *id, const char *signal_name, const char *source, widget_event_info_s event_info)
1996 struct instance *inst;
2000 inst = so_find_instance(pkgname, id);
2002 ErrPrint("Instance %s - %s is not exists (signal_name[%s], source[%s])\n", pkgname, id, signal_name, source);
2003 return WIDGET_ERROR_INVALID_PARAMETER;
2006 l = find_item(inst);
2008 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, signal_name, source);
2009 return WIDGET_ERROR_NOT_EXIST;
2012 item = eina_list_data_get(l);
2014 if (signal_name && source && !strcmp(source, id)) {
2015 if (item->inst->item->has_widget_script) {
2016 if (!strcmp(signal_name, "widget,show")) {
2017 item->is_widget_show = 1;
2019 migrate_to_pending_list_from_hidden_list(item);
2021 if (item->is_widget_updated && !is_pended_item(item)) {
2022 reset_widget_updated_flag(item);
2025 source = util_uri_to_path(source);
2026 } else if (!strcmp(signal_name, "widget,hide")) {
2027 DbgPrint("Livebox(%s) script is hide now\n", id);
2028 item->is_widget_show = 0;
2030 source = util_uri_to_path(source);
2034 if (!strcmp(signal_name, "gbar,show")) {
2035 item->is_gbar_show = 1;
2036 source = util_uri_to_path(source);
2037 } else if (!strcmp(signal_name, "gbar,hide")) {
2038 item->is_gbar_show = 0;
2039 source = util_uri_to_path(source);
2044 ret = so_script_event(inst, signal_name, source, event_info);
2050 if (ret & WIDGET_NEED_TO_SCHEDULE) {
2051 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
2052 (void)append_pending_list(item);
2055 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2056 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
2057 (void)append_force_update_list(item);
2060 if (ret & WIDGET_OUTPUT_UPDATED) {
2061 update_monitor_cnt(item);
2064 return WIDGET_ERROR_NONE;
2067 HAPI int widget_viewer_is_pinned_up(const char *pkgname, const char *id)
2070 struct instance *inst;
2073 inst = so_find_instance(pkgname, id);
2075 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
2076 return WIDGET_ERROR_INVALID_PARAMETER;
2079 l = find_item(inst);
2081 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
2082 return WIDGET_ERROR_NOT_EXIST;
2085 item = eina_list_data_get(l);
2087 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
2088 return WIDGET_ERROR_FAULT;
2093 * Maybe this is not neccessary for this operation
2095 return so_is_pinned_up(inst);
2098 HAPI int widget_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
2101 struct instance *inst;
2105 inst = so_find_instance(pkgname, id);
2107 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
2108 return WIDGET_ERROR_INVALID_PARAMETER;
2111 l = find_item(inst);
2113 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
2114 return WIDGET_ERROR_NOT_EXIST;
2117 item = eina_list_data_get(l);
2119 ret = so_change_group(inst, cluster, category);
2124 if (ret & WIDGET_NEED_TO_SCHEDULE) {
2125 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
2126 (void)append_pending_list(item);
2129 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2130 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
2131 (void)append_force_update_list(item);
2134 if (ret & WIDGET_OUTPUT_UPDATED) {
2135 update_monitor_cnt(item);
2138 return WIDGET_ERROR_NONE;
2141 static int widget_sys_event(struct instance *inst, struct item *item, int event)
2145 ret = so_sys_event(inst, event);
2150 if (ret & WIDGET_NEED_TO_SCHEDULE) {
2151 (void)append_pending_list(item);
2154 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2155 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", item->inst->item->pkgname);
2156 (void)append_force_update_list(item);
2159 if (ret & WIDGET_OUTPUT_UPDATED) {
2160 update_monitor_cnt(item);
2163 return WIDGET_ERROR_NONE;
2166 HAPI int widget_system_event(const char *pkgname, const char *id, int event)
2169 struct instance *inst;
2172 inst = so_find_instance(pkgname, id);
2174 ErrPrint("instance %s - %s is not created\n", pkgname, id);
2175 return WIDGET_ERROR_INVALID_PARAMETER;
2178 l = find_item(inst);
2180 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
2181 return WIDGET_ERROR_NOT_EXIST;
2184 item = eina_list_data_get(l);
2185 return widget_sys_event(inst, item, event);
2188 HAPI int widget_update(const char *pkgname, const char *id, int force)
2191 struct instance *inst;
2194 inst = so_find_instance(pkgname, id);
2196 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
2197 return WIDGET_ERROR_INVALID_PARAMETER;
2200 l = find_item(inst);
2202 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
2203 return WIDGET_ERROR_NOT_EXIST;
2206 item = eina_list_data_get(l);
2207 if (force && gbar_is_opened(pkgname) != GBAR_IS_OPENED) {
2208 (void)append_force_update_list(item);
2210 (void)append_pending_list(item);
2213 return WIDGET_ERROR_NONE;
2216 HAPI int widget_set_content_info(const char *pkgname, const char *id, const char *content_info)
2219 struct instance *inst;
2223 inst = so_find_instance(pkgname, id);
2225 ErrPrint("Instance %s - %s is not created (%s)\n", pkgname, id, content_info);
2226 return WIDGET_ERROR_INVALID_PARAMETER;
2229 l = find_item(inst);
2231 ErrPrint("Instance is not found (%s - %s, %s)\n", pkgname, id, content_info);
2232 return WIDGET_ERROR_NOT_EXIST;
2235 item = eina_list_data_get(l);
2237 ret = so_set_content_info(inst, content_info);
2243 if (ret & WIDGET_NEED_TO_SCHEDULE) {
2244 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
2245 (void)append_pending_list(item);
2248 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2249 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
2250 (void)append_force_update_list(item);
2253 if (ret & WIDGET_OUTPUT_UPDATED) {
2254 update_monitor_cnt(item);
2257 return WIDGET_ERROR_NONE;
2260 HAPI int widget_update_all(const char *pkgname, const char *cluster, const char *category, int force)
2266 DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
2267 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2268 if (item->deleteme) {
2272 if (cluster && strcasecmp(item->inst->cluster, cluster)) {
2276 if (category && strcasecmp(item->inst->category, category)) {
2280 if (pkgname && strlen(pkgname)) {
2281 if (!strcmp(item->inst->item->pkgname, pkgname)) {
2282 if (force && gbar_is_opened(pkgname) != GBAR_IS_OPENED) {
2283 (void)append_force_update_list(item);
2285 (void)append_pending_list(item);
2290 DbgPrint("Update All function doesn't support force update to all widgetes\n");
2292 (void)append_pending_list(item);
2297 return WIDGET_ERROR_NONE;
2300 HAPI int widget_set_content_info_all(const char *pkgname, const char *content)
2305 register int cnt = 0;
2307 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2308 if (item->deleteme) {
2312 if (pkgname && strlen(pkgname)) {
2313 if (!strcmp(item->inst->item->pkgname, pkgname)) {
2314 widget_set_content_info(item->inst->item->pkgname, item->inst->id, content);
2318 widget_set_content_info(item->inst->item->pkgname, item->inst->id, content);
2322 DbgPrint("Update content for %s - %d\n", pkgname ? pkgname : "(all)", cnt);
2324 return WIDGET_ERROR_NONE;
2327 HAPI int widget_delete_all_deleteme(void)
2334 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2335 if (!item->deleteme) {
2339 update_monitor_del(item->inst->id, item);
2340 (void)so_destroy(item->inst, item->unload_so);
2345 DbgPrint("Delete all deleteme: %d\n", cnt);
2346 return WIDGET_ERROR_NONE;
2349 HAPI int widget_delete_all(void)
2356 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2357 update_monitor_del(item->inst->id, item);
2358 (void)so_destroy(item->inst, item->unload_so);
2363 DbgPrint("Delete all deleteme: %d\n", cnt);
2364 return WIDGET_ERROR_NONE;
2367 HAPI int widget_system_event_all(int event)
2373 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2374 if (item->deleteme) {
2378 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
2379 widget_sys_event(item->inst, item, event);
2382 return WIDGET_ERROR_NONE;
2385 HAPI void widget_pause_all(void)
2390 if (s_info.state == STATE_PAUSED) {
2394 s_info.state = STATE_PAUSED;
2396 pending_timer_freeze();
2399 * force timer will not be freezed
2402 EINA_LIST_FOREACH(s_info.item_list, l, item) {
2403 if (item->deleteme) {
2404 DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
2408 if (item->state != STATE_RESUMED) {
2414 widget_sys_event(item->inst, item, WIDGET_SYS_EVENT_PAUSED);
2418 HAPI void widget_resume_all(void)
2424 if (s_info.state == STATE_RESUMED) {
2428 s_info.state = STATE_RESUMED;
2430 pending_timer_thaw();
2434 * force timer will not affected by this
2437 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2438 if (item->deleteme) {
2439 DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
2443 if (item->state != STATE_RESUMED) {
2447 widget_sys_event(item->inst, item, WIDGET_SYS_EVENT_RESUMED);
2449 if (item->updated_in_pause) {
2450 (void)append_pending_list(item);
2451 item->updated_in_pause = 0;
2456 * After send the resume callback, call this function.
2457 * Because the timer_thaw can call the update function.
2458 * Before resumed event is notified to the widget,
2459 * Do not call update function
2461 if (timer_thaw(item) == UPDATE_ITEM_DELETED) {
2462 /* item is deleted */
2467 HAPI int widget_pause(const char *pkgname, const char *id)
2469 struct instance *inst;
2473 inst = so_find_instance(pkgname, id);
2475 return WIDGET_ERROR_INVALID_PARAMETER;
2478 l = find_item(inst);
2480 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2481 return WIDGET_ERROR_NOT_EXIST;
2484 item = eina_list_data_get(l);
2486 return WIDGET_ERROR_FAULT;
2489 if (item->deleteme) {
2490 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
2491 return WIDGET_ERROR_RESOURCE_BUSY;
2494 if (item->state == STATE_PAUSED) {
2495 return WIDGET_ERROR_NONE;
2498 item->state = STATE_PAUSED;
2500 if (s_info.state != STATE_RESUMED) {
2501 return WIDGET_ERROR_NONE;
2506 widget_sys_event(inst, item, WIDGET_SYS_EVENT_PAUSED);
2508 return WIDGET_ERROR_NONE;
2511 HAPI int widget_viewer_connected(const char *pkgname, const char *id, const char *direct_addr)
2513 struct instance *inst;
2515 struct connection *conn_handle;
2518 inst = so_find_instance(pkgname, id);
2520 return WIDGET_ERROR_INVALID_PARAMETER;
2523 l = find_item(inst);
2525 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2526 return WIDGET_ERROR_NOT_EXIST;
2529 item = eina_list_data_get(l);
2531 return WIDGET_ERROR_FAULT;
2534 conn_handle = connection_find_by_addr(direct_addr);
2536 conn_handle = connection_create(direct_addr, (void *)s_table);
2538 ErrPrint("Direct update-path is not supported\n");
2540 DbgPrint("Direct update-path is created: %s\n", id);
2541 item->direct_path_list = eina_list_append(item->direct_path_list, conn_handle);
2544 item->direct_path_list = eina_list_append(item->direct_path_list, conn_handle);
2545 (void)connection_ref(conn_handle);
2548 return WIDGET_ERROR_NONE;
2551 HAPI int widget_viewer_disconnected(const char *pkgname, const char *id, const char *direct_addr)
2553 struct instance *inst;
2556 struct connection *conn_handle;
2558 inst = so_find_instance(pkgname, id);
2560 return WIDGET_ERROR_INVALID_PARAMETER;
2563 l = find_item(inst);
2565 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2566 return WIDGET_ERROR_NOT_EXIST;
2569 item = eina_list_data_get(l);
2571 return WIDGET_ERROR_FAULT;
2574 conn_handle = connection_find_by_addr(direct_addr);
2576 if (eina_list_data_find(item->direct_path_list, conn_handle)) {
2577 item->direct_path_list = eina_list_remove(item->direct_path_list, conn_handle);
2578 connection_unref(conn_handle);
2582 return WIDGET_ERROR_NONE;
2585 HAPI int widget_resume(const char *pkgname, const char *id)
2587 struct instance *inst;
2592 inst = so_find_instance(pkgname, id);
2594 return WIDGET_ERROR_INVALID_PARAMETER;
2597 l = find_item(inst);
2599 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2600 return WIDGET_ERROR_NOT_EXIST;
2603 item = eina_list_data_get(l);
2605 return WIDGET_ERROR_FAULT;
2608 if (item->deleteme) {
2609 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
2610 return WIDGET_ERROR_RESOURCE_BUSY;
2613 if (item->state == STATE_RESUMED) {
2614 return WIDGET_ERROR_NONE;
2617 item->state = STATE_RESUMED;
2619 if (s_info.state != STATE_RESUMED) {
2620 return WIDGET_ERROR_NONE;
2623 widget_sys_event(inst, item, WIDGET_SYS_EVENT_RESUMED);
2625 ret = timer_thaw(item);
2626 if (ret == UPDATE_ITEM_DELETED) {
2631 return WIDGET_ERROR_NONE;
2632 } else if (ret == UPDATE_INVOKED) {
2635 * if the update is successfully done, the updated_in_pause will be reset'd.
2636 * or append it to the pending list
2640 if (item->updated_in_pause) {
2641 (void)append_pending_list(item);
2642 item->updated_in_pause = 0;
2645 return WIDGET_ERROR_NONE;
2648 HAPI void widget_turn_secured_on(void)
2653 HAPI int widget_is_secured(void)
2655 return s_info.secured;
2658 HAPI int widget_is_all_paused(void)
2660 return s_info.state != STATE_RESUMED;
2663 HAPI int widget_set_orientation(const char *pkgname, const char *id, int orientation)
2666 struct instance *inst;
2669 inst = so_find_instance(pkgname, id);
2671 ErrPrint("instance %s - %s is not created\n", pkgname, id);
2672 return WIDGET_ERROR_INVALID_PARAMETER;
2675 l = find_item(inst);
2677 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
2678 return WIDGET_ERROR_NOT_EXIST;
2681 inst->orientation = orientation;
2683 item = eina_list_data_get(l);
2684 return widget_sys_event(inst, item, WIDGET_SYS_EVENT_ORIENTATION_CHANGED);
2687 int widget_provider_app_get_orientation(const char *filename)
2692 EINA_LIST_FOREACH(s_info.item_list, l, item) {
2693 if (!strcmp(widget_util_uri_to_path(item->inst->id), filename)) {
2694 return item->inst->orientation;
2698 return WIDGET_ERROR_NOT_EXIST;