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_provider.h>
27 #include <widget_provider_buffer.h>
28 #include <widget/widget_internal.h>
29 #include <widget/widget.h>
30 #include <widget_errno.h>
31 #include <widget_service.h>
32 #include <widget_service_internal.h>
33 #include <com-core_packet.h>
35 #include "critical_log.h"
37 #include "so_handler.h"
39 #include "update_monitor.h"
42 #include "connection.h"
45 #if defined(_ESTIMATE_PERF)
46 #define ESTIMATE_START(id) DbgPrint("%s START\n", id);
47 #define ESTIMATE_END(id) DbgPrint("%s END\n", id);
49 #define ESTIMATE_START(id)
50 #define ESTIMATE_END(id)
53 #define IS_WIDGET_SHOWN(itm) (!(itm)->inst->item->has_widget_script || ((itm)->inst->item->has_widget_script && (itm)->is_widget_show))
57 #define UPDATE_ITEM_DELETED (-1)
58 #define UPDATE_INVOKED (-2)
59 #define UPDATE_NOT_INVOKED (0)
61 enum gbar_open_state {
62 GBAR_IS_OPENED_BUT_NOT_MINE = -1,
63 GBAR_IS_NOT_OPENED = 0,
75 struct instance *inst;
79 double update_interval;
80 int heavy_updating; /* Only for debugging message */
81 enum state state; /* 1 is paused, 0 is resumed */
84 unsigned int updated_in_pause;
88 int is_widget_updated;
90 Eina_List *direct_path_list;
95 Eina_List *force_update_list;
96 Eina_List *update_list;
97 Eina_List *pending_list;
98 Eina_List *hidden_list;
99 Ecore_Timer *force_update_timer;
100 Ecore_Timer *pending_timer;
101 Eina_List *gbar_open_pending_list;
102 Ecore_Timer *gbar_open_pending_timer;
104 Eina_List *gbar_list;
106 int pending_timer_freezed;
107 int force_timer_freezed;
110 .force_update_list = NULL,
112 .pending_list = NULL,
114 .force_update_timer = NULL,
115 .pending_timer = NULL,
116 .gbar_open_pending_list = NULL,
117 .gbar_open_pending_timer = NULL,
118 .state = STATE_UNKNOWN,
121 .pending_timer_freezed = 0,
122 .force_timer_freezed = 0,
125 static Eina_Bool updator_cb(void *data);
126 static inline void update_monitor_del(const char *id, struct item *item);
127 static int append_force_update_list(struct item *item);
128 static void reset_widget_updated_flag(struct item *item);
129 static int append_pending_list(struct item *item);
131 static void pending_timer_freeze(void)
133 DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
134 if (!s_info.pending_timer) {
138 if (!s_info.pending_timer_freezed) {
139 DbgPrint("Freeze the pending timer\n");
140 ecore_timer_freeze(s_info.pending_timer);
143 s_info.pending_timer_freezed++;
146 static void pending_timer_thaw(void)
148 DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
149 if (!s_info.pending_timer_freezed) {
153 if (!s_info.pending_timer) {
154 s_info.pending_timer_freezed = 0;
158 s_info.pending_timer_freezed--;
159 if (!s_info.pending_timer_freezed) {
160 DbgPrint("Thaw the pending timer\n");
161 ecore_timer_thaw(s_info.pending_timer);
165 static void force_timer_freeze(void)
167 DbgPrint("Freeze force timer: %d\n", s_info.force_timer_freezed);
168 if (!s_info.force_update_timer) {
172 if (!s_info.force_timer_freezed) {
173 DbgPrint("Force timer freezed\n");
174 ecore_timer_freeze(s_info.force_update_timer);
177 s_info.force_timer_freezed++;
180 static void force_timer_thaw(void)
182 DbgPrint("Freezed force count: %d\n", s_info.force_timer_freezed);
183 if (!s_info.force_timer_freezed) {
187 if (!s_info.force_update_timer) {
188 s_info.force_timer_freezed = 0;
192 s_info.force_timer_freezed--;
193 if (!s_info.force_timer_freezed) {
194 DbgPrint("Thaw the force timer\n");
195 ecore_timer_thaw(s_info.force_update_timer);
200 * -1 : GBAR is opened, but not mine
201 * 0 : GBAR is not opened
202 * 1 : my GBAR is opened
204 static inline enum gbar_open_state gbar_is_opened(const char *pkgname)
208 struct instance *inst;
211 EINA_LIST_FOREACH(s_info.gbar_list, l, inst) {
212 if (pkgname && !strcmp(pkgname, inst->item->pkgname)) {
213 return GBAR_IS_OPENED;
219 return i > 0 ? GBAR_IS_OPENED_BUT_NOT_MINE : GBAR_IS_NOT_OPENED;
222 static Eina_Bool gbar_open_pended_cmd_consumer_cb(void *data)
226 item = eina_list_nth(s_info.gbar_open_pending_list, 0);
231 if (eina_list_data_find(s_info.update_list, item)) {
232 return ECORE_CALLBACK_RENEW;
235 s_info.gbar_open_pending_list = eina_list_remove(s_info.gbar_open_pending_list, item);
238 * To prevent from checking the is_updated function
240 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
241 /* Item is destroyed */
244 if (s_info.gbar_open_pending_list) {
245 return ECORE_CALLBACK_RENEW;
249 s_info.gbar_open_pending_timer = NULL;
250 return ECORE_CALLBACK_CANCEL;
253 static Eina_Bool update_timeout_cb(void *data)
259 ErrPrint("UPDATE TIMEOUT ========> %s - %s\n", item->inst->item->pkgname, item->inst->id);
261 if (!eina_list_data_find(s_info.update_list, item)) {
262 ErrPrint("Updating item is not matched\n");
265 fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
266 fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,timeout", NO_ALARM, DEFAULT_LIFE_TIMER);
267 s_info.update_list = eina_list_remove(s_info.update_list, item);
270 return ECORE_CALLBACK_CANCEL;
273 static inline void update_monitor_cnt(struct item *item)
278 now = util_timestamp();
279 interval = now - item->update_interval;
283 * If the content update is processed in too short time,
284 * don't increase the monitor counter, instead of it
285 * set the heavy updating flag.
286 * And handling this heavy updating from the
287 * file update callback.
289 if (interval >= MINIMUM_UPDATE_INTERVAL) {
290 if (eina_list_data_find(s_info.update_list, item)) {
293 * If already in updating mode,
294 * reset the monitor_cnt to 1,
295 * all updated event will be merged into A inotify event
297 DbgPrint("While waiting updated event, content is updated [%s]\n", item->inst->id);
298 item->monitor_cnt = 1;
303 item->heavy_updating = 1;
306 item->update_interval = now;
309 static inline void do_force_update(struct item *item)
313 if (item->monitor) { /*!< If this item is already in update process */
317 if (!IS_WIDGET_SHOWN(item)) {
318 DbgPrint("%s is not shown yet. it will be added to normal pending list\n", item->inst->item->pkgname);
319 (void)append_force_update_list(item);
323 if (item->state != STATE_RESUMED) {
324 DbgPrint("Item is paused. but it will be updated forcely(%s)\n", item->inst->item->pkgname);
327 item->updated_in_pause = 0;
329 ret = so_is_updated(item->inst);
331 if (so_need_to_destroy(item->inst) == WIDGET_NEED_TO_DESTROY) {
332 widget_provider_send_deleted(item->inst->item->pkgname, item->inst->id);
333 widget_destroy(item->inst->item->pkgname, item->inst->id, WIDGET_DESTROY_TYPE_DEFAULT);
336 * Every caller of this, must not access the item from now.
341 reset_widget_updated_flag(item);
347 * Check the update_list, if you want make serialized update
349 if (/*s_info.update_list || */gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED_BUT_NOT_MINE) {
350 DbgPrint("%s is busy, migrate to normal pending list\n", item->inst->id);
351 (void)append_pending_list(item);
355 item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
356 if (!item->monitor) {
357 ErrPrint("Failed to add update monitor %s(%s):%d\n",
358 item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
362 ret = so_update(item->inst);
364 ecore_timer_del(item->monitor);
365 item->monitor = NULL;
366 reset_widget_updated_flag(item);
372 * Counter of the event monitor is only used for asynchronous content updating,
373 * So reset it to 1 from here because the async updating is started now,
374 * even if it is accumulated by other event function before this.
376 item->monitor_cnt = 1;
380 * While waiting the Callback function call,
381 * Add this for finding the crash
383 fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
385 if (ret & WIDGET_NEED_TO_SCHEDULE) {
386 (void)append_pending_list(item);
389 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
390 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", item->inst->item->pkgname);
391 (void)append_force_update_list(item);
394 if (ret & WIDGET_OUTPUT_UPDATED) {
397 * In this case, there is potential issue
398 * 1. User added update CALLBACK -> Inotify event (Only once)
399 * > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
400 * 2. Inotify event -> User added update CALLBACK -> Inotify event
401 * > Okay. What we want is this.
403 update_monitor_cnt(item);
408 * This should be updated after "update_monitor_cnt" function call,
409 * because the update_monitor_cnt function will see the s_info.update variable,
411 s_info.update_list = eina_list_append(s_info.update_list, item);
416 static Eina_Bool force_update_cb(void *data)
420 item = eina_list_nth(s_info.force_update_list, 0);
425 s_info.force_update_list = eina_list_remove(s_info.force_update_list, item);
427 do_force_update(item);
429 if (s_info.force_update_list) {
430 return ECORE_CALLBACK_RENEW;
434 s_info.force_update_timer = NULL;
435 return ECORE_CALLBACK_CANCEL;
438 static inline __attribute__((always_inline)) int activate_force_update_consumer(void)
440 if (s_info.force_update_timer) {
441 return WIDGET_ERROR_NONE;
444 s_info.force_update_timer = ecore_timer_add(0.000001f, force_update_cb, NULL);
445 if (!s_info.force_update_timer) {
446 ErrPrint("Failed to add a new force update timer\n");
447 return WIDGET_ERROR_FAULT;
450 DbgPrint("Force update timer is registered\n");
452 return WIDGET_ERROR_NONE;
455 static inline void deactivate_force_update_consumer(void)
457 if (!s_info.force_update_timer) {
461 ecore_timer_del(s_info.force_update_timer);
462 s_info.force_update_timer = NULL;
464 DbgPrint("Force update timer is deleted\n");
467 static Eina_Bool pended_cmd_consumer_cb(void *data)
471 item = eina_list_nth(s_info.pending_list, 0);
476 if (eina_list_data_find(s_info.update_list, item) || gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED_BUT_NOT_MINE) {
477 return ECORE_CALLBACK_RENEW;
480 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
483 * To prevent from checking the is_updated function
485 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
486 /* item is destroyed */
489 if (s_info.pending_list) {
490 return ECORE_CALLBACK_RENEW;
494 s_info.pending_timer = NULL;
495 s_info.pending_timer_freezed = 0;
496 return ECORE_CALLBACK_CANCEL;
499 static inline __attribute__((always_inline)) int activate_pending_consumer(void)
501 if (s_info.pending_timer) {
502 return WIDGET_ERROR_NONE;
505 s_info.pending_timer = ecore_timer_add(0.000001f, pended_cmd_consumer_cb, NULL);
506 if (!s_info.pending_timer) {
507 ErrPrint("Failed to add a new pended command consumer\n");
508 return WIDGET_ERROR_FAULT;
512 * Do not increase the freezed counter.
513 * Just freeze the timer.
515 if (s_info.pending_timer_freezed) {
516 ecore_timer_freeze(s_info.pending_timer);
519 return WIDGET_ERROR_NONE;
522 static inline void deactivate_pending_consumer(void)
524 if (!s_info.pending_timer) {
528 ecore_timer_del(s_info.pending_timer);
529 s_info.pending_timer = NULL;
530 s_info.pending_timer_freezed = 0;
533 static inline void deactivate_gbar_open_pending_consumer(void)
535 if (!s_info.gbar_open_pending_timer) {
539 ecore_timer_del(s_info.gbar_open_pending_timer);
540 s_info.gbar_open_pending_timer = NULL;
543 static inline int __attribute__((always_inline)) activate_gbar_open_pending_consumer(void)
545 if (s_info.gbar_open_pending_timer) {
549 s_info.gbar_open_pending_timer = ecore_timer_add(0.000001f, gbar_open_pended_cmd_consumer_cb, NULL);
550 if (!s_info.gbar_open_pending_timer) {
551 ErrPrint("Failed to add a new pended command consumer\n");
552 return WIDGET_ERROR_FAULT;
558 static inline void migrate_to_gbar_open_pending_list(const char *pkgname)
565 EINA_LIST_FOREACH_SAFE(s_info.pending_list, l, n, item) {
566 if (strcmp(pkgname, item->inst->item->pkgname)) {
570 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
571 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
576 * These items will be moved to the pending list after the GBAR is closed.
577 * Force list -> pd open list -> pending list.
578 * So there is no way to go back to the foce update list again.
581 * the ITEM must only exists in one list, pending list or force_update_list
582 * It is not accepted to exists in two list at same time.
584 EINA_LIST_FOREACH_SAFE(s_info.force_update_list, l, n, item) {
585 if (strcmp(pkgname, item->inst->item->pkgname)) {
589 s_info.force_update_list = eina_list_remove(s_info.force_update_list, item);
590 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
594 if (s_info.gbar_open_pending_list) {
595 activate_gbar_open_pending_consumer();
598 if (!s_info.pending_list) {
599 deactivate_pending_consumer();
602 if (!s_info.force_update_list) {
603 deactivate_force_update_consumer();
607 static inline void migrate_to_pending_list(const char *pkgname)
614 EINA_LIST_FOREACH_SAFE(s_info.gbar_open_pending_list, l, n, item) {
615 if (strcmp(pkgname, item->inst->item->pkgname)) {
619 s_info.gbar_open_pending_list = eina_list_remove(s_info.gbar_open_pending_list, item);
620 s_info.pending_list = eina_list_append(s_info.pending_list, item);
624 if (s_info.pending_list) {
625 activate_pending_consumer();
628 if (!s_info.gbar_open_pending_list) {
629 deactivate_gbar_open_pending_consumer();
633 static inline int is_pended_item(struct item *item)
635 struct item *in_item;
636 if (gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED) {
637 in_item = eina_list_data_find(s_info.gbar_open_pending_list, item);
639 in_item = eina_list_data_find(s_info.pending_list, item);
642 return (in_item == item);
645 static int append_pending_list(struct item *item)
647 if (item->deleteme) {
648 DbgPrint("Item will be deleted, ignore update request: %s\n", item->inst->id);
649 return WIDGET_ERROR_RESOURCE_BUSY;
652 if (eina_list_data_find(s_info.force_update_list, item)) {
653 DbgPrint("Already exists in force list\n");
654 return WIDGET_ERROR_NONE;
657 if (gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED) {
658 if (eina_list_data_find(s_info.gbar_open_pending_list, item) == item) {
659 DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
660 return WIDGET_ERROR_ALREADY_EXIST;
663 if (activate_gbar_open_pending_consumer() < 0) {
664 ErrPrint("Failed to activate GBAR open pending consumer\n");
665 return WIDGET_ERROR_FAULT;
668 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
670 if (eina_list_data_find(s_info.pending_list, item) == item) {
671 DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
672 return WIDGET_ERROR_ALREADY_EXIST;
675 if (IS_WIDGET_SHOWN(item)) {
676 if (activate_pending_consumer() < 0) {
677 return WIDGET_ERROR_FAULT;
680 s_info.pending_list = eina_list_append(s_info.pending_list, item);
682 if (eina_list_data_find(s_info.hidden_list, item) == item) {
683 DbgPrint("Already in hidden list - %s\n", item->inst->item->pkgname);
684 return WIDGET_ERROR_ALREADY_EXIST;
687 s_info.hidden_list = eina_list_append(s_info.hidden_list, item);
691 return WIDGET_ERROR_NONE;
694 static inline int clear_from_pending_list(struct item *item)
699 EINA_LIST_FOREACH(s_info.pending_list, l, tmp) {
704 s_info.pending_list = eina_list_remove_list(s_info.pending_list, l);
705 if (!s_info.pending_list) {
706 deactivate_pending_consumer();
708 return WIDGET_ERROR_NONE;
711 return WIDGET_ERROR_NOT_EXIST;
714 static int append_force_update_list(struct item *item)
716 if (item->deleteme) {
717 DbgPrint("Item will be deleted, ignore force update request: %s\n", item->inst->id);
718 return WIDGET_ERROR_RESOURCE_BUSY;
722 * If the item is already in pending list, remove it.
724 clear_from_pending_list(item);
726 if (gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED) {
727 if (eina_list_data_find(s_info.gbar_open_pending_list, item) == item) {
728 DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
729 return WIDGET_ERROR_ALREADY_EXIST;
732 if (activate_gbar_open_pending_consumer() < 0) {
733 ErrPrint("Failed to activate GBAR open pending consumer\n");
734 return WIDGET_ERROR_FAULT;
737 s_info.gbar_open_pending_list = eina_list_append(s_info.gbar_open_pending_list, item);
739 if (eina_list_data_find(s_info.force_update_list, item)) {
740 DbgPrint("Already in force update list\n");
741 return WIDGET_ERROR_NONE;
744 if (IS_WIDGET_SHOWN(item)) {
745 if (activate_force_update_consumer() < 0) {
746 return WIDGET_ERROR_FAULT;
749 s_info.force_update_list = eina_list_append(s_info.force_update_list, item);
751 if (eina_list_data_find(s_info.hidden_list, item) == item) {
752 DbgPrint("Already in hidden list - %s\n", item->inst->id);
753 return WIDGET_ERROR_ALREADY_EXIST;
756 s_info.hidden_list = eina_list_append(s_info.hidden_list, item);
758 DbgPrint("forced item is moved to hidden_list - %s\n", item->inst->id);
762 return WIDGET_ERROR_NONE;
765 static inline int clear_from_force_update_list(struct item *item)
770 EINA_LIST_FOREACH(s_info.force_update_list, l, tmp) {
775 s_info.force_update_list = eina_list_remove_list(s_info.force_update_list, l);
776 if (!s_info.force_update_list) {
777 deactivate_force_update_consumer();
780 return WIDGET_ERROR_NONE;
783 return WIDGET_ERROR_NOT_EXIST;
786 static inline void migrate_to_pending_list_from_hidden_list(struct item *item)
788 if (!eina_list_data_find(s_info.hidden_list, item)) {
792 s_info.hidden_list = eina_list_remove(s_info.hidden_list, item);
793 append_pending_list(item);
798 * This function can call the update callback
799 * return 0 if there is no changes
800 * return -1 the item is deleted
802 static inline int timer_thaw(struct item *item)
813 ecore_timer_thaw(item->timer);
814 period = ecore_timer_interval_get(item->timer);
815 pending = ecore_timer_pending_get(item->timer);
816 delay = util_time_delay_for_compensation(period) - pending;
817 ecore_timer_delay(item->timer, delay);
819 if (item->sleep_at == 0.0f) {
823 sleep_time = util_timestamp() - item->sleep_at;
824 item->sleep_at = 0.0f;
826 if (sleep_time > pending) {
829 * Before do updating forcely, clear it from the pending list.
830 * We will consume it from here now.
832 (void)clear_from_pending_list(item);
834 if (updator_cb(item) == ECORE_CALLBACK_CANCEL) {
835 /* item is destroyed */
836 return UPDATE_ITEM_DELETED;
838 return UPDATE_INVOKED;
842 return UPDATE_NOT_INVOKED;
845 static void timer_freeze(struct item *item)
851 ecore_timer_freeze(item->timer);
853 if (ecore_timer_interval_get(item->timer) <= 1.0f) {
857 #if defined(_USE_ECORE_TIME_GET)
858 item->sleep_at = ecore_time_get();
861 if (gettimeofday(&tv, NULL) < 0) {
862 ErrPrint("gettimeofday: %d\n", errno);
867 item->sleep_at = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
871 static inline Eina_List *find_item(struct instance *inst)
876 EINA_LIST_FOREACH(s_info.item_list, l, item) {
877 if (item->inst == inst) {
885 static int desc_updated_cb(const char *filename, void *data, int over)
890 WarnPrint("Event Q overflow\n");
895 DbgPrint("DESC %s is updated\n", filename);
896 if (item->is_gbar_show) {
897 widget_damage_region_s region = {
904 widget_provider_send_updated(item->inst->item->pkgname, item->inst->id, WIDGET_PRIMARY_BUFFER, ®ion, 1, filename);
906 ErrPrint("But GBAR is not opened, Ignore this update (%s)\n", item->inst->id);
911 static inline int output_handler(struct item *item)
916 if (item->monitor_cnt < 0 || item->heavy_updating) {
917 if (!item->heavy_updating) {
918 WarnPrint("%s has invalid monitor_cnt\n", item->inst->id);
921 item->heavy_updating = 0; /* Reset flag */
924 item->monitor_cnt = 0;
927 if (item->monitor_cnt == 0) {
929 fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
933 ecore_timer_del(item->monitor);
934 item->monitor = NULL;
937 s_info.update_list = eina_list_remove(s_info.update_list, item);
939 if (item->deleteme) {
940 update_monitor_del(item->inst->id, item);
941 widget_provider_send_deleted(item->inst->item->pkgname, item->inst->id);
942 (void)so_destroy(item->inst, item->unload_so);
951 static int file_updated_cb(const char *filename, void *data, int over)
957 char *content = NULL;
964 WarnPrint("Event Q overflow\n");
969 if (item->deleteme) {
970 DbgPrint("Item is in deleting process. (%s)\n", filename);
974 ESTIMATE_START(item->inst->id);
976 ret = util_get_filesize(filename);
978 ErrPrint("Content is updated. but invalid. ret = %d (Update is ignored)\n", ret);
979 ESTIMATE_END(item->inst->id);
980 return EXIT_SUCCESS; /*!< To keep the callback */
983 ret = so_get_output_info(item->inst, &w, &h, &priority, &content, &title);
985 ErrPrint("widget_get_info returns %d\n", ret);
986 ESTIMATE_END(item->inst->id);
987 return EXIT_SUCCESS; /*!< To keep the callback */
991 * Alternative information can be NOT_IMPLEMENTED
992 * And we can ignore its error.
994 ret = so_get_alt_info(item->inst, &icon, &name);
996 ErrPrint("widget_get_alt_info returns %d (ignored)\n", ret);
999 if (IS_WIDGET_SHOWN(item)) {
1000 widget_damage_region_s region = {
1007 * If the content is not written on shared buffer (pixmap, shm, raw file, ...)
1008 * We cannot use the direct path for sending updated event.
1010 widget_provider_send_extra_info(item->inst->item->pkgname, item->inst->id, item->inst->priority,
1011 content, title, item->inst->icon, item->inst->name);
1012 widget_provider_send_updated(item->inst->item->pkgname, item->inst->id, WIDGET_PRIMARY_BUFFER, ®ion, 0, NULL);
1014 item->is_widget_updated++;
1017 ESTIMATE_END(item->inst->id);
1019 return output_handler(item);
1022 static void reset_widget_updated_flag(struct item *item)
1024 widget_damage_region_s region = {
1031 if (!item->is_widget_updated) {
1035 DbgPrint("[%s] Updated %d times, (content: %s), (title: %s)\n",
1036 item->inst->id, item->is_widget_updated,
1037 item->inst->content, item->inst->title);
1040 * If the content is not written on shared buffer (pixmap, shm, raw file, ...)
1041 * We cannot use the direct path for sending updated event.
1043 widget_provider_send_extra_info(item->inst->item->pkgname, item->inst->id, item->inst->priority,
1044 item->inst->content, item->inst->title, item->inst->icon, item->inst->name);
1045 widget_provider_send_updated(item->inst->item->pkgname, item->inst->id, WIDGET_PRIMARY_BUFFER, ®ion, 0, NULL);
1047 item->is_widget_updated = 0;
1050 static inline int clear_from_gbar_open_pending_list(struct item *item)
1055 EINA_LIST_FOREACH(s_info.gbar_open_pending_list, l, tmp) {
1060 s_info.gbar_open_pending_list = eina_list_remove_list(s_info.gbar_open_pending_list, l);
1061 if (!s_info.gbar_open_pending_list) {
1062 deactivate_gbar_open_pending_consumer();
1064 return WIDGET_ERROR_NONE;
1067 return WIDGET_ERROR_NOT_EXIST;
1072 * This must has to return ECORE_CALLBACK_CANCEL, only if the item is deleted.
1073 * So every caller, should manage the deleted item correctly.
1075 static Eina_Bool updator_cb(void *data)
1082 if (item->monitor) { /*!< If this item is already in update process */
1083 return ECORE_CALLBACK_RENEW;
1086 if (!IS_WIDGET_SHOWN(item)) {
1087 DbgPrint("%s is not shown yet. make delay for updates\n", item->inst->item->pkgname);
1088 (void)append_pending_list(item);
1089 return ECORE_CALLBACK_RENEW;
1092 if (item->state != STATE_RESUMED) {
1093 item->updated_in_pause++;
1094 DbgPrint("%s is paused[%d]. make delay for updating\n", item->inst->item->pkgname, item->updated_in_pause);
1095 return ECORE_CALLBACK_RENEW;
1098 item->updated_in_pause = 0;
1100 ret = so_is_updated(item->inst);
1102 if (so_need_to_destroy(item->inst) == WIDGET_NEED_TO_DESTROY) {
1103 widget_provider_send_deleted(item->inst->item->pkgname, item->inst->id);
1104 widget_destroy(item->inst->item->pkgname, item->inst->id, WIDGET_DESTROY_TYPE_DEFAULT);
1107 * Every caller of this, must not access the item from now.
1109 return ECORE_CALLBACK_CANCEL;
1112 reset_widget_updated_flag(item);
1113 return ECORE_CALLBACK_RENEW;
1118 * Check the update_list, if you want make serialized update
1120 if (/*s_info.update_list || */gbar_is_opened(item->inst->item->pkgname) == GBAR_IS_OPENED_BUT_NOT_MINE) {
1121 DbgPrint("%s is busy\n", item->inst->id);
1122 (void)append_pending_list(item);
1123 return ECORE_CALLBACK_RENEW;
1126 item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
1127 if (!item->monitor) {
1128 ErrPrint("Failed to add update monitor %s(%s):%d\n",
1129 item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
1130 return ECORE_CALLBACK_RENEW;
1133 ret = so_update(item->inst);
1135 ecore_timer_del(item->monitor);
1136 item->monitor = NULL;
1137 reset_widget_updated_flag(item);
1138 return ECORE_CALLBACK_RENEW;
1143 * Counter of the event monitor is only used for asynchronous content updating,
1144 * So reset it to 1 from here because the async updating is started now,
1145 * even if it is accumulated by other event function before this.
1147 item->monitor_cnt = 1;
1151 * While waiting the Callback function call,
1152 * Add this for finding the crash
1154 fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
1156 if (ret & WIDGET_NEED_TO_SCHEDULE) {
1157 (void)append_pending_list(item);
1160 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
1161 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", item->inst->item->pkgname);
1162 (void)append_force_update_list(item);
1165 if (ret & WIDGET_OUTPUT_UPDATED) {
1168 * In this case, there is potential issue
1169 * 1. User added update CALLBACK -> Inotify event (Only once)
1170 * > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
1171 * 2. Inotify event -> User added update CALLBACK -> Inotify event
1172 * > Okay. What we want is this.
1174 update_monitor_cnt(item);
1179 * This should be updated after "update_monitor_cnt" function call,
1180 * because the update_monitor_cnt function will see the s_info.update variable,
1182 s_info.update_list = eina_list_append(s_info.update_list, item);
1184 return ECORE_CALLBACK_RENEW;
1187 static inline void update_monitor_del(const char *id, struct item *item)
1192 tmp = (char *)util_uri_to_path(id);
1194 ErrPrint("Invalid parameter\n");
1198 update_monitor_del_update_cb(tmp, file_updated_cb);
1200 len = strlen(tmp) + strlen(".desc") + 1;
1203 ErrPrint("malloc: %d (%s.desc)\n", errno, util_uri_to_path(id));
1207 snprintf(tmp, len, "%s.desc", util_uri_to_path(id));
1208 update_monitor_del_update_cb(tmp, desc_updated_cb);
1212 static inline int add_desc_update_monitor(const char *id, struct item *item)
1218 len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
1219 filename = malloc(len);
1221 ErrPrint("malloc: %d (%s.desc)\n", errno, util_uri_to_path(id));
1222 return WIDGET_ERROR_OUT_OF_MEMORY;
1225 snprintf(filename, len, "%s.desc", util_uri_to_path(id));
1226 ret = update_monitor_add_update_cb(filename, desc_updated_cb, item);
1231 static inline int add_file_update_monitor(const char *id, struct item *item)
1233 return update_monitor_add_update_cb(util_uri_to_path(id), file_updated_cb, item);
1236 static inline int update_monitor_add(const char *id, struct item *item)
1240 * item->inst is not available yet.
1242 add_file_update_monitor(id, item);
1243 add_desc_update_monitor(id, item);
1244 return WIDGET_ERROR_NONE;
1247 static int disconnected_cb(int handle, void *data)
1253 struct connection *connection;
1254 struct connection *conn_handle;
1256 connection = connection_find_by_fd(handle);
1261 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1262 EINA_LIST_FOREACH_SAFE(item->direct_path_list, k, n, conn_handle) {
1263 if (conn_handle == connection) {
1264 item->direct_path_list = eina_list_remove(item->direct_path_list, conn_handle);
1265 (void)connection_unref(conn_handle);
1273 HAPI void widget_viewer_init(void)
1276 ret = connection_add_event_handler(CONNECTION_EVENT_TYPE_DISCONNECTED, disconnected_cb, NULL);
1278 ErrPrint("Unable to add an event handler\n");
1283 HAPI void widget_viewer_fini(void)
1287 ret = widget_delete_all_deleteme();
1289 DbgPrint("Delete all deleteme: %d\n", ret);
1292 ret = widget_delete_all();
1294 DbgPrint("Delete all: %d\n", ret);
1297 /* Just for in case of ... */
1298 deactivate_pending_consumer();
1299 deactivate_gbar_open_pending_consumer();
1301 eina_list_free(s_info.gbar_open_pending_list);
1302 s_info.gbar_open_pending_list = NULL;
1303 eina_list_free(s_info.pending_list);
1304 s_info.pending_list = NULL;
1306 (void)connection_del_event_handler(CONNECTION_EVENT_TYPE_DISCONNECTED, disconnected_cb);
1312 * Exported API for each widgetes.
1314 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)
1318 int ret = WIDGET_ERROR_NOT_EXIST;
1319 widget_damage_region_s region = {
1326 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1327 if (strcmp(item->inst->item->pkgname, pkgname) || strcmp(item->inst->id, id)) {
1331 if (item->direct_path_list) {
1333 struct connection *conn_handle;
1334 EINA_LIST_FOREACH(item->direct_path_list, l, conn_handle) {
1335 ret = widget_provider_send_direct_updated(connection_handle(conn_handle), pkgname, id, idx, ®ion, gbar, descfile);
1338 ret = widget_provider_send_updated(pkgname, id, idx, ®ion, gbar, descfile);
1347 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)
1351 int ret = WIDGET_ERROR_NOT_EXIST;
1352 widget_damage_region_s region = {
1359 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1360 if (strcmp(item->inst->item->pkgname, pkgname) || strcmp(item->inst->id, id)) {
1364 if (item->direct_path_list) {
1366 struct connection *conn_handle;
1367 EINA_LIST_FOREACH(item->direct_path_list, l, conn_handle) {
1368 ret = widget_provider_send_direct_buffer_updated(connection_handle(conn_handle), handle, idx, ®ion, gbar, descfile);
1371 ret = widget_provider_send_buffer_updated(handle, idx, ®ion, gbar, descfile);
1380 const char *widget_find_pkgname(const char *filename)
1385 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1386 if (!strcmp(item->inst->id, filename)) {
1387 return item->inst->item->pkgname;
1394 int widget_update_extra_info(const char *id, const char *content, const char *title, const char *icon, const char *name)
1399 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1400 if (!strcmp(item->inst->id, id)) {
1401 if (content && strlen(content)) {
1404 _content = strdup(content);
1406 if (item->inst->content) {
1407 free(item->inst->content);
1408 item->inst->content = NULL;
1411 item->inst->content = _content;
1413 ErrPrint("strdup: %d\n", errno);
1417 if (title && strlen(title)) {
1420 _title = strdup(title);
1422 if (item->inst->title) {
1423 free(item->inst->title);
1424 item->inst->title = NULL;
1427 item->inst->title = _title;
1429 ErrPrint("strdup: %d\n", errno);
1433 if (icon && strlen(icon)) {
1436 _icon = strdup(icon);
1438 if (item->inst->icon) {
1439 free(item->inst->icon);
1440 item->inst->icon = NULL;
1443 item->inst->icon = _icon;
1445 ErrPrint("strdup: %d\n", errno);
1449 if (name && strlen(name)) {
1452 _name = strdup(name);
1454 if (item->inst->name) {
1455 free(item->inst->name);
1456 item->inst->name = NULL;
1459 item->inst->name = _name;
1461 ErrPrint("strdup: %d\n", errno);
1465 return WIDGET_ERROR_NONE;
1469 return WIDGET_ERROR_NOT_EXIST;
1472 int widget_request_update_by_id(const char *filename)
1477 if (so_current_op() != WIDGET_OP_UNKNOWN) {
1478 ErrPrint("Current operation: %d\n", so_current_op());
1481 * Some case requires to update the content of other widget from widget_XXX ABI.
1482 * In that case this function can be used so we have not to filter it from here.
1483 * ex) Setting accessibility.
1484 * Press the assistive light, turned on, need to update other instances too.
1485 * Then the widget will use this function from widget_clicked function.
1489 EINA_LIST_FOREACH(s_info.item_list, l, item) {
1490 if (!strcmp(item->inst->id, filename)) {
1491 return append_pending_list(item);
1495 return WIDGET_ERROR_NOT_EXIST;
1498 int widget_trigger_update_monitor(const char *filename, int is_gbar)
1503 if (so_current_op() != WIDGET_OP_UNKNOWN) {
1504 ErrPrint("Current operation: %d\n", so_current_op());
1505 return WIDGET_ERROR_INVALID_PARAMETER;
1510 len = strlen(filename) + strlen(".desc");
1512 fname = malloc(len + 1);
1514 ErrPrint("malloc: %d\n", errno);
1515 return WIDGET_ERROR_OUT_OF_MEMORY;
1518 snprintf(fname, len, "%s.desc", filename);
1520 fname = strdup(filename);
1522 ErrPrint("strdup: %d\n", errno);
1523 return WIDGET_ERROR_OUT_OF_MEMORY;
1527 if (access(fname, R_OK | W_OK) != 0) {
1528 ErrPrint("access: %s (%d)\n", fname, errno);
1529 ret = WIDGET_ERROR_IO_ERROR;
1531 ret = update_monitor_trigger_update_cb(fname, 0);
1538 HAPI int widget_open_gbar(const char *pkgname, const char *id)
1540 struct instance *inst;
1541 struct instance *tmp;
1544 inst = so_find_instance(pkgname, id);
1546 ErrPrint("Instance is not found\n");
1547 return WIDGET_ERROR_NOT_EXIST;
1550 EINA_LIST_FOREACH(s_info.gbar_list, l, tmp) {
1556 if (!s_info.gbar_list) {
1557 pending_timer_freeze();
1561 * Freeze the force timer only in this case.
1563 force_timer_freeze();
1566 s_info.gbar_list = eina_list_append(s_info.gbar_list, inst);
1569 * Find all instances from the pending list.
1570 * Move them to gbar_open_pending_timer
1572 migrate_to_gbar_open_pending_list(pkgname);
1573 return WIDGET_ERROR_NONE;
1576 HAPI int widget_close_gbar(const char *pkgname, const char *id)
1580 struct instance *tmp;
1581 struct instance *inst;
1583 inst = so_find_instance(pkgname, id);
1585 ErrPrint("Insatnce is not found\n");
1586 return WIDGET_ERROR_NOT_EXIST;
1589 EINA_LIST_FOREACH_SAFE(s_info.gbar_list, l, n, tmp) {
1594 s_info.gbar_list = eina_list_remove(s_info.gbar_list, tmp);
1595 if (!s_info.gbar_list) {
1596 pending_timer_thaw();
1601 * Move all items in gbar_open_pending_list
1604 migrate_to_pending_list(pkgname);
1605 return WIDGET_ERROR_NONE;
1608 return WIDGET_ERROR_NOT_EXIST;
1611 static struct method s_table[] = {
1618 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)
1620 struct instance *inst;
1630 inst = so_find_instance(pkgname, id);
1632 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);
1633 return WIDGET_ERROR_NONE;
1636 if (!arg->skip_need_to_create) {
1637 ret = so_create_needed(pkgname, arg->cluster, arg->category, arg->abi);
1638 if (ret != WIDGET_NEED_TO_CREATE) {
1639 return WIDGET_ERROR_PERMISSION_DENIED;
1645 item = calloc(1, sizeof(*item));
1647 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);
1648 return WIDGET_ERROR_OUT_OF_MEMORY;
1651 ret = update_monitor_add(id, item);
1657 if (arg->direct_addr) {
1658 struct connection *conn_handle;
1660 conn_handle = connection_find_by_addr(arg->direct_addr);
1662 conn_handle = connection_create(arg->direct_addr, (void *)s_table);
1664 ErrPrint("Direct update-path is not supported\n");
1666 DbgPrint("Direct update-path is created: %s\n", id);
1667 item->direct_path_list = eina_list_append(item->direct_path_list, conn_handle);
1670 item->direct_path_list = eina_list_append(item->direct_path_list, connection_ref(conn_handle));
1671 DbgPrint("Direct update-path is referred: %s\n", id);
1675 create_ret = so_create(pkgname, id, arg->content, arg->timeout, arg->has_widget_script, arg->cluster, arg->category, arg->abi, &inst);
1676 if (create_ret < 0) {
1677 struct connection *conn_handle;
1679 update_monitor_del(id, item);
1680 EINA_LIST_FREE(item->direct_path_list, conn_handle) {
1681 (void)connection_unref(conn_handle);
1692 item->state = STATE_UNKNOWN;
1694 if (arg->period > 0.0f && !s_info.secured) {
1695 item->timer = util_timer_add(arg->period, updator_cb, item);
1697 struct connection *conn_handle;
1698 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);
1699 update_monitor_del(id, item);
1700 EINA_LIST_FREE(item->direct_path_list, conn_handle) {
1701 (void)connection_unref(conn_handle);
1703 (void)so_destroy(inst, item->unload_so);
1705 return WIDGET_ERROR_FAULT;
1708 if (s_info.state == STATE_PAUSED) {
1712 DbgPrint("Local update timer is disabled: %lf (%d)\n", arg->period, s_info.secured);
1716 s_info.item_list = eina_list_append(s_info.item_list, item);
1718 if (create_ret & WIDGET_NEED_TO_SCHEDULE) {
1719 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
1720 (void)append_pending_list(item);
1723 if (create_ret & WIDGET_FORCE_TO_SCHEDULE) {
1724 DbgPrint("%s Returns WIDGET_NEED_TO_FORCE_UPDATE\n", pkgname);
1725 (void)append_force_update_list(item);
1728 if (create_ret & WIDGET_OUTPUT_UPDATED) {
1729 update_monitor_cnt(item);
1732 * To send a output info, get the info forcely.
1733 * but the output file monitor will do this again
1735 * This function will set the tmp_content and tmp_title
1736 * even if it has no updates on the content, title,
1737 * it will set them to NULL.
1739 if (so_get_output_info(inst, w, h, priority, content, title) == (int)WIDGET_ERROR_NONE) {
1743 tmp = strdup(*content);
1745 ErrPrint("strdup: %d\n", errno);
1754 tmp = strdup(*title);
1756 ErrPrint("strdup: %d\n", errno);
1766 *priority = inst->priority;
1767 return need_to_create;
1770 HAPI int widget_destroy(const char *pkgname, const char *id, int type)
1774 struct instance *inst;
1775 struct instance *tmp;
1777 struct connection *conn_handle;
1779 inst = so_find_instance(pkgname, id);
1781 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1782 return WIDGET_ERROR_INVALID_PARAMETER;
1785 EINA_LIST_FOREACH_SAFE(s_info.gbar_list, l, n, tmp) {
1790 s_info.gbar_list = eina_list_remove(s_info.gbar_list, tmp);
1791 if (!s_info.gbar_list) {
1792 pending_timer_thaw();
1797 * Move all items in gbar_open_pending_list
1800 migrate_to_pending_list(pkgname);
1804 l = find_item(inst);
1806 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1807 return WIDGET_ERROR_NOT_EXIST;
1810 item = eina_list_data_get(l);
1811 s_info.item_list = eina_list_remove_list(s_info.item_list, l);
1813 s_info.update_list = eina_list_remove(s_info.update_list, item);
1814 s_info.hidden_list = eina_list_remove(s_info.hidden_list, item);
1815 clear_from_gbar_open_pending_list(item);
1816 clear_from_pending_list(item);
1817 clear_from_force_update_list(item);
1818 EINA_LIST_FREE(item->direct_path_list, conn_handle) {
1819 (void)connection_unref(conn_handle);
1823 ecore_timer_del(item->timer);
1828 * To keep the previous status, we should or'ing the value.
1830 item->unload_so = (item->unload_so || (type == WIDGET_DESTROY_TYPE_UNINSTALL) || (type == WIDGET_DESTROY_TYPE_UPGRADE));
1832 if (item->monitor) {
1835 update_monitor_del(id, item);
1836 (void)so_destroy(inst, item->unload_so);
1840 return WIDGET_ERROR_NONE;
1843 HAPI int widget_viewer_resize_widget(const char *pkgname, const char *id, int w, int h)
1846 struct instance *inst;
1850 inst = so_find_instance(pkgname, id);
1852 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
1853 return WIDGET_ERROR_INVALID_PARAMETER;
1856 l = find_item(inst);
1858 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
1859 return WIDGET_ERROR_NOT_EXIST;
1862 item = eina_list_data_get(l);
1865 ret = so_resize(inst, w, h);
1871 if (ret & WIDGET_NEED_TO_SCHEDULE) {
1872 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
1873 (void)append_pending_list(item);
1876 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
1877 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
1878 (void)append_force_update_list(item);
1881 if (ret & WIDGET_OUTPUT_UPDATED) {
1882 update_monitor_cnt(item);
1885 return WIDGET_ERROR_NONE;
1888 HAPI char *widget_pinup(const char *pkgname, const char *id, int pinup)
1890 struct instance *inst;
1893 inst = so_find_instance(pkgname, id);
1895 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1899 ret = so_pinup(inst, pinup);
1903 HAPI int widget_viewer_set_period(const char *pkgname, const char *id, double period)
1906 struct instance *inst;
1909 inst = so_find_instance(pkgname, id);
1911 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1912 return WIDGET_ERROR_INVALID_PARAMETER;
1915 l = find_item(inst);
1917 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1918 return WIDGET_ERROR_NOT_EXIST;
1921 item = eina_list_data_get(l);
1923 if (period <= 0.0f) {
1925 ecore_timer_del(item->timer);
1930 util_timer_interval_set(item->timer, period);
1931 } else if (!s_info.secured) {
1932 item->timer = util_timer_add(period, updator_cb, item);
1934 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1935 return WIDGET_ERROR_FAULT;
1938 if (s_info.state == STATE_PAUSED) {
1944 return WIDGET_ERROR_NONE;
1947 HAPI int widget_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1950 struct instance *inst;
1954 inst = so_find_instance(pkgname, id);
1956 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1957 return WIDGET_ERROR_INVALID_PARAMETER;
1960 l = find_item(inst);
1962 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1963 return WIDGET_ERROR_NOT_EXIST;
1966 item = eina_list_data_get(l);
1969 ret = so_clicked(inst, event, timestamp, x, y);
1975 if (ret & WIDGET_NEED_TO_SCHEDULE) {
1976 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
1977 (void)append_pending_list(item);
1980 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
1981 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
1982 (void)append_force_update_list(item);
1985 if (ret & WIDGET_OUTPUT_UPDATED) {
1986 update_monitor_cnt(item);
1989 return WIDGET_ERROR_NONE;
1992 HAPI int widget_script_event(const char *pkgname, const char *id, const char *signal_name, const char *source, widget_event_info_s event_info)
1995 struct instance *inst;
1999 inst = so_find_instance(pkgname, id);
2001 ErrPrint("Instance %s - %s is not exists (signal_name[%s], source[%s])\n", pkgname, id, signal_name, source);
2002 return WIDGET_ERROR_INVALID_PARAMETER;
2005 l = find_item(inst);
2007 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, signal_name, source);
2008 return WIDGET_ERROR_NOT_EXIST;
2011 item = eina_list_data_get(l);
2013 if (signal_name && source && !strcmp(source, id)) {
2014 if (item->inst->item->has_widget_script) {
2015 if (!strcmp(signal_name, "widget,show")) {
2016 item->is_widget_show = 1;
2018 migrate_to_pending_list_from_hidden_list(item);
2020 if (item->is_widget_updated && !is_pended_item(item)) {
2021 reset_widget_updated_flag(item);
2024 source = util_uri_to_path(source);
2025 } else if (!strcmp(signal_name, "widget,hide")) {
2026 DbgPrint("Livebox(%s) script is hide now\n", id);
2027 item->is_widget_show = 0;
2029 source = util_uri_to_path(source);
2033 if (!strcmp(signal_name, "gbar,show")) {
2034 item->is_gbar_show = 1;
2035 source = util_uri_to_path(source);
2036 } else if (!strcmp(signal_name, "gbar,hide")) {
2037 item->is_gbar_show = 0;
2038 source = util_uri_to_path(source);
2043 ret = so_script_event(inst, signal_name, source, event_info);
2049 if (ret & WIDGET_NEED_TO_SCHEDULE) {
2050 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
2051 (void)append_pending_list(item);
2054 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2055 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
2056 (void)append_force_update_list(item);
2059 if (ret & WIDGET_OUTPUT_UPDATED) {
2060 update_monitor_cnt(item);
2063 return WIDGET_ERROR_NONE;
2066 HAPI int widget_viewer_is_pinned_up(const char *pkgname, const char *id)
2069 struct instance *inst;
2072 inst = so_find_instance(pkgname, id);
2074 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
2075 return WIDGET_ERROR_INVALID_PARAMETER;
2078 l = find_item(inst);
2080 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
2081 return WIDGET_ERROR_NOT_EXIST;
2084 item = eina_list_data_get(l);
2086 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
2087 return WIDGET_ERROR_FAULT;
2092 * Maybe this is not neccessary for this operation
2094 return so_is_pinned_up(inst);
2097 HAPI int widget_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
2100 struct instance *inst;
2104 inst = so_find_instance(pkgname, id);
2106 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
2107 return WIDGET_ERROR_INVALID_PARAMETER;
2110 l = find_item(inst);
2112 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
2113 return WIDGET_ERROR_NOT_EXIST;
2116 item = eina_list_data_get(l);
2118 ret = so_change_group(inst, cluster, category);
2123 if (ret & WIDGET_NEED_TO_SCHEDULE) {
2124 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
2125 (void)append_pending_list(item);
2128 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2129 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
2130 (void)append_force_update_list(item);
2133 if (ret & WIDGET_OUTPUT_UPDATED) {
2134 update_monitor_cnt(item);
2137 return WIDGET_ERROR_NONE;
2140 static int widget_sys_event(struct instance *inst, struct item *item, int event)
2144 ret = so_sys_event(inst, event);
2149 if (ret & WIDGET_NEED_TO_SCHEDULE) {
2150 (void)append_pending_list(item);
2153 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2154 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", item->inst->item->pkgname);
2155 (void)append_force_update_list(item);
2158 if (ret & WIDGET_OUTPUT_UPDATED) {
2159 update_monitor_cnt(item);
2162 return WIDGET_ERROR_NONE;
2165 HAPI int widget_system_event(const char *pkgname, const char *id, int event)
2168 struct instance *inst;
2171 inst = so_find_instance(pkgname, id);
2173 ErrPrint("instance %s - %s is not created\n", pkgname, id);
2174 return WIDGET_ERROR_INVALID_PARAMETER;
2177 l = find_item(inst);
2179 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
2180 return WIDGET_ERROR_NOT_EXIST;
2183 item = eina_list_data_get(l);
2184 return widget_sys_event(inst, item, event);
2187 HAPI int widget_update(const char *pkgname, const char *id, int force)
2190 struct instance *inst;
2193 inst = so_find_instance(pkgname, id);
2195 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
2196 return WIDGET_ERROR_INVALID_PARAMETER;
2199 l = find_item(inst);
2201 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
2202 return WIDGET_ERROR_NOT_EXIST;
2205 item = eina_list_data_get(l);
2206 if (force && gbar_is_opened(pkgname) != GBAR_IS_OPENED) {
2207 (void)append_force_update_list(item);
2209 (void)append_pending_list(item);
2212 return WIDGET_ERROR_NONE;
2215 HAPI int widget_set_content_info(const char *pkgname, const char *id, const char *content_info)
2218 struct instance *inst;
2222 inst = so_find_instance(pkgname, id);
2224 ErrPrint("Instance %s - %s is not created (%s)\n", pkgname, id, content_info);
2225 return WIDGET_ERROR_INVALID_PARAMETER;
2228 l = find_item(inst);
2230 ErrPrint("Instance is not found (%s - %s, %s)\n", pkgname, id, content_info);
2231 return WIDGET_ERROR_NOT_EXIST;
2234 item = eina_list_data_get(l);
2236 ret = so_set_content_info(inst, content_info);
2242 if (ret & WIDGET_NEED_TO_SCHEDULE) {
2243 DbgPrint("%s Returns WIDGET_NEED_TO_SCHEDULE\n", pkgname);
2244 (void)append_pending_list(item);
2247 if (ret & WIDGET_FORCE_TO_SCHEDULE) {
2248 DbgPrint("%s Return WIDGET_NEED_TO_FORCE_SCHEDULE\n", pkgname);
2249 (void)append_force_update_list(item);
2252 if (ret & WIDGET_OUTPUT_UPDATED) {
2253 update_monitor_cnt(item);
2256 return WIDGET_ERROR_NONE;
2259 HAPI int widget_update_all(const char *pkgname, const char *cluster, const char *category, int force)
2265 DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
2266 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2267 if (item->deleteme) {
2271 if (cluster && strcasecmp(item->inst->cluster, cluster)) {
2275 if (category && strcasecmp(item->inst->category, category)) {
2279 if (pkgname && strlen(pkgname)) {
2280 if (!strcmp(item->inst->item->pkgname, pkgname)) {
2281 if (force && gbar_is_opened(pkgname) != GBAR_IS_OPENED) {
2282 (void)append_force_update_list(item);
2284 (void)append_pending_list(item);
2289 DbgPrint("Update All function doesn't support force update to all widgetes\n");
2291 (void)append_pending_list(item);
2296 return WIDGET_ERROR_NONE;
2299 HAPI int widget_set_content_info_all(const char *pkgname, const char *content)
2304 register int cnt = 0;
2306 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2307 if (item->deleteme) {
2311 if (pkgname && strlen(pkgname)) {
2312 if (!strcmp(item->inst->item->pkgname, pkgname)) {
2313 widget_set_content_info(item->inst->item->pkgname, item->inst->id, content);
2317 widget_set_content_info(item->inst->item->pkgname, item->inst->id, content);
2321 DbgPrint("Update content for %s - %d\n", pkgname ? pkgname : "(all)", cnt);
2323 return WIDGET_ERROR_NONE;
2326 HAPI int widget_delete_all_deleteme(void)
2333 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2334 if (!item->deleteme) {
2338 update_monitor_del(item->inst->id, item);
2339 (void)so_destroy(item->inst, item->unload_so);
2344 DbgPrint("Delete all deleteme: %d\n", cnt);
2345 return WIDGET_ERROR_NONE;
2348 HAPI int widget_delete_all(void)
2355 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2356 update_monitor_del(item->inst->id, item);
2357 (void)so_destroy(item->inst, item->unload_so);
2362 DbgPrint("Delete all deleteme: %d\n", cnt);
2363 return WIDGET_ERROR_NONE;
2366 HAPI int widget_system_event_all(int event)
2372 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2373 if (item->deleteme) {
2377 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
2378 widget_sys_event(item->inst, item, event);
2381 return WIDGET_ERROR_NONE;
2384 HAPI void widget_pause_all(void)
2389 if (s_info.state == STATE_PAUSED) {
2393 s_info.state = STATE_PAUSED;
2395 pending_timer_freeze();
2398 * force timer will not be freezed
2401 EINA_LIST_FOREACH(s_info.item_list, l, item) {
2402 if (item->deleteme) {
2403 DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
2407 if (item->state != STATE_RESUMED) {
2413 widget_sys_event(item->inst, item, WIDGET_SYS_EVENT_PAUSED);
2417 HAPI void widget_resume_all(void)
2423 if (s_info.state == STATE_RESUMED) {
2427 s_info.state = STATE_RESUMED;
2429 pending_timer_thaw();
2433 * force timer will not affected by this
2436 EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
2437 if (item->deleteme) {
2438 DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
2442 if (item->state != STATE_RESUMED) {
2446 widget_sys_event(item->inst, item, WIDGET_SYS_EVENT_RESUMED);
2448 if (item->updated_in_pause) {
2449 (void)append_pending_list(item);
2450 item->updated_in_pause = 0;
2455 * After send the resume callback, call this function.
2456 * Because the timer_thaw can call the update function.
2457 * Before resumed event is notified to the widget,
2458 * Do not call update function
2460 if (timer_thaw(item) == UPDATE_ITEM_DELETED) {
2461 /* item is deleted */
2466 HAPI int widget_pause(const char *pkgname, const char *id)
2468 struct instance *inst;
2472 inst = so_find_instance(pkgname, id);
2474 return WIDGET_ERROR_INVALID_PARAMETER;
2477 l = find_item(inst);
2479 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2480 return WIDGET_ERROR_NOT_EXIST;
2483 item = eina_list_data_get(l);
2485 return WIDGET_ERROR_FAULT;
2488 if (item->deleteme) {
2489 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
2490 return WIDGET_ERROR_RESOURCE_BUSY;
2493 if (item->state == STATE_PAUSED) {
2494 return WIDGET_ERROR_NONE;
2497 item->state = STATE_PAUSED;
2499 if (s_info.state != STATE_RESUMED) {
2500 return WIDGET_ERROR_NONE;
2505 widget_sys_event(inst, item, WIDGET_SYS_EVENT_PAUSED);
2507 return WIDGET_ERROR_NONE;
2510 HAPI int widget_viewer_connected(const char *pkgname, const char *id, const char *direct_addr)
2512 struct instance *inst;
2514 struct connection *conn_handle;
2517 inst = so_find_instance(pkgname, id);
2519 return WIDGET_ERROR_INVALID_PARAMETER;
2522 l = find_item(inst);
2524 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2525 return WIDGET_ERROR_NOT_EXIST;
2528 item = eina_list_data_get(l);
2530 return WIDGET_ERROR_FAULT;
2533 conn_handle = connection_find_by_addr(direct_addr);
2535 conn_handle = connection_create(direct_addr, (void *)s_table);
2537 ErrPrint("Direct update-path is not supported\n");
2539 DbgPrint("Direct update-path is created: %s\n", id);
2540 item->direct_path_list = eina_list_append(item->direct_path_list, conn_handle);
2543 item->direct_path_list = eina_list_append(item->direct_path_list, conn_handle);
2544 (void)connection_ref(conn_handle);
2547 return WIDGET_ERROR_NONE;
2550 HAPI int widget_viewer_disconnected(const char *pkgname, const char *id, const char *direct_addr)
2552 struct instance *inst;
2555 struct connection *conn_handle;
2557 inst = so_find_instance(pkgname, id);
2559 return WIDGET_ERROR_INVALID_PARAMETER;
2562 l = find_item(inst);
2564 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2565 return WIDGET_ERROR_NOT_EXIST;
2568 item = eina_list_data_get(l);
2570 return WIDGET_ERROR_FAULT;
2573 conn_handle = connection_find_by_addr(direct_addr);
2575 if (eina_list_data_find(item->direct_path_list, conn_handle)) {
2576 item->direct_path_list = eina_list_remove(item->direct_path_list, conn_handle);
2577 connection_unref(conn_handle);
2581 return WIDGET_ERROR_NONE;
2584 HAPI int widget_resume(const char *pkgname, const char *id)
2586 struct instance *inst;
2591 inst = so_find_instance(pkgname, id);
2593 return WIDGET_ERROR_INVALID_PARAMETER;
2596 l = find_item(inst);
2598 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
2599 return WIDGET_ERROR_NOT_EXIST;
2602 item = eina_list_data_get(l);
2604 return WIDGET_ERROR_FAULT;
2607 if (item->deleteme) {
2608 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
2609 return WIDGET_ERROR_RESOURCE_BUSY;
2612 if (item->state == STATE_RESUMED) {
2613 return WIDGET_ERROR_NONE;
2616 item->state = STATE_RESUMED;
2618 if (s_info.state != STATE_RESUMED) {
2619 return WIDGET_ERROR_NONE;
2622 widget_sys_event(inst, item, WIDGET_SYS_EVENT_RESUMED);
2624 ret = timer_thaw(item);
2625 if (ret == UPDATE_ITEM_DELETED) {
2630 return WIDGET_ERROR_NONE;
2631 } else if (ret == UPDATE_INVOKED) {
2634 * if the update is successfully done, the updated_in_pause will be reset'd.
2635 * or append it to the pending list
2639 if (item->updated_in_pause) {
2640 (void)append_pending_list(item);
2641 item->updated_in_pause = 0;
2644 return WIDGET_ERROR_NONE;
2647 HAPI void widget_turn_secured_on(void)
2652 HAPI int widget_is_secured(void)
2654 return s_info.secured;
2657 HAPI int widget_is_all_paused(void)
2659 return s_info.state != STATE_RESUMED;