diff options
Diffstat (limited to 'home/src/widget.c')
-rw-r--r-- | home/src/widget.c | 1103 |
1 files changed, 1103 insertions, 0 deletions
diff --git a/home/src/widget.c b/home/src/widget.c new file mode 100644 index 0000000..0d070b8 --- /dev/null +++ b/home/src/widget.c @@ -0,0 +1,1103 @@ +/* + * Samsung API + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Flora License, Version 1.1 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <Elementary.h> +#include <widget_service.h> +#include <widget_service_internal.h> +#include <widget_errno.h> +#include <stdbool.h> +#include <dlog.h> +#include <bundle.h> +#include <efl_assist.h> +#include <Ecore_X.h> +#include <widget.h> +#include <vconf.h> +#include <app_preference.h> +#include <widget_viewer_evas_internal.h> /* feed_access_event */ +#include <widget_viewer_evas.h> + +/** + * WIDGET_ACCESS_STATUS_XXX + */ +#include <widget_service_internal.h> + +#include "util.h" +#include "db.h" +#include "index.h" +#include "layout_info.h" +#include "log.h" +#include "main.h" +#include "page_info.h" +#include "scroller_info.h" +#include "scroller.h" +#include "page.h" +#include "edit.h" +#include "add-viewer_package.h" +#include "add-viewer_pkgmgr.h" + + +static struct info { + Eina_Bool is_scrolling; + Eina_List *pended_event_list; +} s_info = { + .is_scrolling = EINA_FALSE, + .pended_event_list = NULL, +}; + + + +#define MAX_TTL 10 +#define TAG_SCROLL "l.s" // Scroller +#define TAG_UPDATED "l.u" // Widget Updated +#define TAG_FAULT_HL "f.h" // Faulted Highlight (emulate) +#define FAULTED_HL_TIMER 0.00001f + + + +struct pended_access_event { + Evas_Object *widget; + Elm_Access_Action_Info info; + void (*cb)(Evas_Object *obj, int ret, void *data); + void *data; + int ttl; +}; + + + +static const char *action_type_string(int type) +{ + switch (type) { + case ELM_ACCESS_ACTION_HIGHLIGHT: + return "HL"; + case ELM_ACCESS_ACTION_UNHIGHLIGHT: + return "UNHL"; + case ELM_ACCESS_ACTION_HIGHLIGHT_NEXT: + return "NEXT"; + case ELM_ACCESS_ACTION_HIGHLIGHT_PREV: + return "PREV"; + case ELM_ACCESS_ACTION_VALUE_CHANGE: + return "VALUE_CHANGE"; + case ELM_ACCESS_ACTION_MOUSE: + return "MOUSE"; + case ELM_ACCESS_ACTION_BACK: + return "BACK"; + case ELM_ACCESS_ACTION_OVER: + return "OVER"; + case ELM_ACCESS_ACTION_READ: + return "READ"; + case ELM_ACCESS_ACTION_ENABLE: + return "ENABLE"; + case ELM_ACCESS_ACTION_DISABLE: + return "DISABLE"; + case ELM_ACCESS_ACTION_ACTIVATE: + return "ACTIVATE"; + case ELM_ACCESS_ACTION_SCROLL: + return "SCROLL"; + default: + return "Unknown"; + } +} + +static void push_pended_event_list(Evas_Object *obj, Elm_Access_Action_Info *info, void (*cb)(Evas_Object *obj, int ret, void *data), void *data) +{ + struct pended_access_event *_info; + + _info = malloc(sizeof(*_info)); + if (!_info) { + _E("malloc:%s\n", strerror(errno)); + return; + } + + memcpy(&_info->info, info, sizeof(*info)); + _info->widget = obj; + _info->cb = cb; + _info->data = data; + _info->ttl = MAX_TTL; + + s_info.pended_event_list = eina_list_append(s_info.pended_event_list, _info); +} + + + +static void try_again_send_event(struct pended_access_event *info) +{ + if (info->ttl < 0) { + _E("Event TTL reach to the end"); + free(info); + return; + } + + s_info.pended_event_list = eina_list_prepend(s_info.pended_event_list, info); +} + + + +static struct pended_access_event *pop_pended_event_list(void) +{ + struct pended_access_event *info; + + info = eina_list_nth(s_info.pended_event_list, 0); + if (info) { + s_info.pended_event_list = eina_list_remove(s_info.pended_event_list, info); + info->ttl--; + } + + return info; +} + + + +static void widget_pended_event_consumer(Evas_Object *obj, int ret, void *data) +{ + struct pended_access_event *info; + + info = pop_pended_event_list(); + if (info) { + int ret; + ret = widget_viewer_evas_feed_access_event(info->widget, info->info.action_type, &info->info, info->cb, info->data); + if (ret == WIDGET_ERROR_RESOURCE_BUSY) { + _E("Failed to send pended event (%s), %X", action_type_string(info->info.action_type), ret); + try_again_send_event(info); + } else { + free(info); + } + } +} + + + +static void send_access_event(Evas_Object *widget, Elm_Access_Action_Info *info, int must_be_sent, void (*cb)(Evas_Object *obj, int ret, void *data), void *data) +{ + int ret; + + ret = widget_viewer_evas_feed_access_event(widget, info->action_type, info, cb, data); + if (ret == WIDGET_ERROR_RESOURCE_BUSY && must_be_sent) { + _D("Pending event (%s)", action_type_string(info->action_type)); + push_pended_event_list(widget, info, cb, data); + } +} + + + +static void del_cb(void *data, Evas *e, Evas_Object *widget, void *event_info) +{ + const char *widget_id; + struct pended_access_event *info; + Eina_List *l; + Eina_List *n; + + EINA_LIST_FOREACH_SAFE(s_info.pended_event_list, l, n, info) { + if (info->widget == widget) { + s_info.pended_event_list = eina_list_remove(s_info.pended_event_list, info); + free(info); + } + } + + widget_id = widget_viewer_evas_get_widget_id(widget); + if (widget_id) { + struct add_viewer_package *pkginfo; + + pkginfo = add_viewer_package_find(widget_id); + if (!pkginfo) { + _E("Add viewer has no info: %s", widget_id); + } else { + add_viewer_package_set_skip(pkginfo, 0); + } + } else { + _E("Has no widget_id?"); + } +} + + + +static void _widget_created_cb(void *data, Evas_Object *obj, void *event_info) +{ +} + + + +static void _widget_updated_cb(void *data, Evas_Object *obj, void *event_info) +{ + int (*updated)(Evas_Object *obj); + + updated = evas_object_data_get(obj, TAG_UPDATED); + if (!updated) { + return; + } + + if (updated(obj) == ECORE_CALLBACK_CANCEL) { + evas_object_data_del(obj, TAG_UPDATED); + } +} + + + +static void _widget_control_scroll_cb(void *data, Evas_Object *obj, void *event_info) +{ + struct widget_evas_event_info *ev = event_info; + int (*scroll)(Evas_Object *obj, int hold); + + scroll = evas_object_data_get(obj, TAG_SCROLL); + if (!scroll) { + return; + } + + if (scroll(obj, (ev->error == WIDGET_ERROR_NONE && ev->event == WIDGET_EVENT_HOLD_SCROLL)) == ECORE_CALLBACK_CANCEL) { + evas_object_data_del(obj, TAG_SCROLL); + } +} + + + +HAPI Evas_Object *widget_create(Evas_Object *parent, const char *id, const char *subid, double period) +{ + Evas_Object *widget = NULL; + char *pkgname = NULL; + struct add_viewer_package *pkginfo; + + retv_if(!id, NULL); + + pkgname = widget_service_get_widget_id(id); + if (pkgname) { + free(pkgname); + } else { + _D("%s is not installed in the pkgmgr DB", id); + return NULL; + } + + widget = widget_viewer_evas_add_widget(parent, id, subid, period); + retv_if(!widget, NULL); + + pkginfo = add_viewer_package_find(id); + if (!pkginfo) { + _E("add-viewer info none: %s", id); + } else { + if (add_viewer_package_is_skipped(pkginfo)) { + _E("Package marked as skip"); + } + + add_viewer_package_set_skip(pkginfo, 1); + _D("Mark added: %s", id); + } + + evas_object_event_callback_add(widget, EVAS_CALLBACK_DEL, del_cb, NULL); + evas_object_smart_callback_add(widget, WIDGET_SMART_SIGNAL_WIDGET_CREATED, _widget_created_cb, NULL); + evas_object_smart_callback_add(widget, WIDGET_SMART_SIGNAL_UPDATED, _widget_updated_cb, NULL); + evas_object_smart_callback_add(widget, WIDGET_SMART_SIGNAL_CONTROL_SCROLLER, _widget_control_scroll_cb, NULL); + return widget; +} + + + +HAPI void widget_destroy(Evas_Object *widget) +{ + ret_if(!widget); + + evas_object_smart_callback_del(widget, WIDGET_SMART_SIGNAL_WIDGET_CREATED, _widget_created_cb); + evas_object_smart_callback_del(widget, WIDGET_SMART_SIGNAL_UPDATED, _widget_updated_cb); + evas_object_smart_callback_del(widget, WIDGET_SMART_SIGNAL_CONTROL_SCROLLER, _widget_control_scroll_cb); + evas_object_del(widget); +} + + + +/* The content is updated */ +static void _widget_extra_updated_cb(void *data, Evas_Object *obj, void *event_info) +{ + Evas_Object *page = data; + layout_info_s *layout_info = NULL; + scroller_info_s *scroller_info = NULL; + page_info_s *page_info = NULL; + const char *content_info = NULL; + + int center_index = 0; + int page_index = 0; + int ordering; + + ret_if(!page); + + _D("Widget is updated"); + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + ret_if(!page_info); + ret_if(!page_info->item); + + layout_info = evas_object_data_get(page_info->layout, DATA_KEY_LAYOUT_INFO); + ret_if(!layout_info); + + content_info = widget_viewer_evas_get_content_info(page_info->item); + ret_if(!content_info); + + free(page_info->subid); + page_info->subid = strdup(content_info); + ret_if(!page_info->subid); + + /* do not need to update DB on the edit mode */ + if (layout_info->edit) return; + + scroller_info = evas_object_data_get(page_info->scroller, DATA_KEY_SCROLLER_INFO); + ret_if(!scroller_info); + + center_index = scroller_seek_page_position(page_info->scroller, scroller_info->center); + page_index = scroller_seek_page_position(page_info->scroller, page); + ordering = page_index - center_index - 1; + + db_update_item_by_ordering(page_info->id, content_info, ordering); + + _SD("Widget is updated to [%s:%s:%d]", page_info->id, content_info, ordering); +} + + + +static void _widget_remove(Evas_Object *page) +{ + Evas_Object *proxy_page = NULL; + Evas_Object *page_current = NULL; + Evas_Object *scroller = NULL; + page_info_s *page_info = NULL; + + /* We have to delete a proxy page on the edit mode */ + proxy_page = evas_object_data_get(page, DATA_KEY_PROXY_PAGE); + if (proxy_page) { + scroller_info_s *scroller_info = NULL; + page_info_s *proxy_page_info = NULL; + + proxy_page_info = evas_object_data_get(proxy_page, DATA_KEY_PAGE_INFO); + ret_if(!proxy_page_info); + + scroller = proxy_page_info->scroller; + ret_if(!scroller); + + scroller_info = evas_object_data_get(scroller, DATA_KEY_SCROLLER_INFO); + ret_if(!scroller_info); + ret_if(!scroller_info->parent); + + scroller_pop_page(proxy_page_info->scroller, proxy_page); + edit_destroy_proxy_page(proxy_page); + + page_current = scroller_get_focused_page(scroller); + ret_if(!page_current); + + index_bring_in_page(scroller_info->index[PAGE_DIRECTION_RIGHT], page_current); + edit_change_focus(scroller, page_current); + edit_arrange_plus_page(scroller_info->parent); + } + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + ret_if(!page_info); + + _D("Widget(%s) is removed", page_info->id); + + scroller = page_info->scroller; + ret_if(!scroller); + + scroller_pop_page(page_info->scroller, page); + page_destroy(page); + if (!main_get_info()->is_tts) { + page_arrange_plus_page(scroller, 0); + } +} + + + +static void _widget_create_aborted_cb(void *data, Evas_Object *obj, void *event_info) +{ + struct widget_evas_event_info *ev = event_info; + Evas_Object *page = data; + Eina_List *page_info_list = NULL; + layout_info_s *layout_info = NULL; + page_info_s *page_info = NULL; + + ret_if(!page); + + _D("Widget is aborted to create"); + + /* We have to get the page_info before removing it */ + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + ret_if(!page_info); + + layout_info = evas_object_data_get(page_info->layout, DATA_KEY_LAYOUT_INFO); + ret_if(!layout_info); + + if (ev->error == WIDGET_ERROR_ALREADY_EXIST) { + _SW("Already exists %s", ev->widget_app_id); + _widget_remove(page); + } else if (ev->error == WIDGET_ERROR_DISABLED) { + _SW("Disable %s", ev->widget_app_id); + _widget_remove(page); + page_info_list = scroller_write_list(layout_info->scroller); + if (page_info_list) { + db_read_list(page_info_list); + page_info_list_destroy(page_info_list); + } else { + db_remove_all_item(); + } + } +} + + + +static void _widget_period_changed_cb(void *data, Evas_Object *obj, void *event_info) +{ + struct widget_evas_event_info *ev = event_info; + _SD("Period changed: %s -> %lf", ev->widget_app_id, widget_viewer_evas_get_period(obj)); + /* + * TODO: Update the period information - Sync with DB? + */ +} + + + +static void _widget_faulted_cb(void *data, Evas_Object *obj, void *event_info) +{ + struct widget_evas_event_info *ev = event_info; + + _SD("Widget is faulted - %s", ev->widget_app_id); +} + + + +static void _widget_deleted_cb(void *data, Evas_Object *obj, void *event_info) +{ + struct widget_evas_event_info *ev = event_info; + Evas_Object *page = data; + page_info_s *page_info = NULL; + + ret_if(!page); + + _D("Widget is deleted"); + + if (ev->error == WIDGET_ERROR_FAULT) { + /* DBox is faulted. */ + _SE("Widget is faulted - %s", ev->widget_app_id); + return; + } + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + ret_if(!page_info); + + if (!widget_viewer_evas_is_faulted(page_info->item)) { + _widget_remove(page); + } +} + + + +static void _widget_access_action_ret_cb(Evas_Object *obj, int ret, void *data) +{ + Evas_Object *page = data; + page_info_s *page_info; + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + ret_if(!page_info); + + switch (ret) { + case WIDGET_ACCESS_STATUS_FIRST: + case WIDGET_ACCESS_STATUS_LAST: + { + Elm_Access_Action_Info action_info; + memset(&action_info, 0, sizeof(action_info)); + action_info.action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT; + push_pended_event_list(page_info->item, &action_info, widget_pended_event_consumer, NULL); + } + case WIDGET_ACCESS_STATUS_ERROR: /* In case of error, we have to set focus on our page */ + page_info->need_to_unhighlight = EINA_FALSE; + page_info->highlight_changed = EINA_FALSE; + page_info->need_to_read = EINA_TRUE; + + /* Update highlight */ + _D("The result of access action is (%d) %s", ret, page_info->highlighted ? "hl" : "unhl"); + elm_access_highlight_set(page_info->focus); + break; + case WIDGET_ACCESS_STATUS_DONE: + case WIDGET_ACCESS_STATUS_READ: + default: + if (page_info->highlighted) { + page_info->need_to_unhighlight = EINA_TRUE; + if (!page_info->highlight_changed) { + page_info->highlight_changed = EINA_TRUE; + _D("Need to unhighlight"); + elm_access_highlight_set(page_info->focus); + } else { + _D("Do not change the highlight"); + } + } else { + _D("page_info->highlight EINA_FALSE"); + } + } + + widget_pended_event_consumer(obj, ret, data); +} + + + +static Eina_Bool _highlight_action_cb(void *data, Evas_Object *focus, Elm_Access_Action_Info *action_info) +{ + Evas_Object *page = data; + page_info_s *page_info; + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + if (!page_info) { + _E("Page info is not valid\n"); + return EINA_FALSE; + } + + if (page_info->highlighted == EINA_FALSE) { + page_info->highlighted = EINA_TRUE; + page_info->need_to_read = EINA_TRUE; + _D("Turn on highlight"); + return EINA_FALSE; + } + + if (page_info->need_to_unhighlight) { + page_info->need_to_unhighlight = EINA_FALSE; + _D("Turn off highlight"); + return EINA_TRUE; + } else { + _D("Turn on highlight"); + return EINA_FALSE; + } +} + + + +static Eina_Bool _unhighlight_action_cb(void *data, Evas_Object *focus, Elm_Access_Action_Info *action_info) +{ + Evas_Object *page = data; + page_info_s *page_info; + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + if (!page_info) { + _E("Page info is not valid\n"); + return EINA_FALSE; + } + + if (page_info->highlighted == EINA_TRUE) { + Elm_Access_Action_Info _action_info; + + _D("Reset highlight flags"); + page_info->highlighted = EINA_FALSE; + page_info->highlight_changed = EINA_FALSE; + + memset(&_action_info, 0, sizeof(_action_info)); + if (s_info.is_scrolling) { + if (page_info->is_scrolled_object) { + page_info->is_scrolled_object = EINA_FALSE; + + if (widget_viewer_evas_is_faulted(page_info->item)) { + _D("Faulted"); + return EINA_FALSE; + } + + // We have to cancelate the scroll event. + _action_info.mouse_type = 2; // MOUSE_UP + _action_info.action_type = ELM_ACCESS_ACTION_SCROLL; + send_access_event(page_info->item, &_action_info, 1, widget_pended_event_consumer, NULL); + + _action_info.mouse_type = 0; + _action_info.action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT; + send_access_event(page_info->item, &_action_info, 1, widget_pended_event_consumer, NULL); + _D("Reset scroll event"); + } + } else { + // Need to turn of highlight + _action_info.action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT; + send_access_event(page_info->item, &_action_info, 1, widget_pended_event_consumer, NULL); + } + return EINA_FALSE; + } + + _D("Unhighlighted"); + return EINA_TRUE; +} + + + +static Eina_Bool _access_action_activate_cb(void *data, Evas_Object *focus, Elm_Access_Action_Info *action_info) +{ + Evas_Object *page = data; + page_info_s *page_info; + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + if (!page_info) { + _E("Page info is not valid\n"); + /* Do not change the highlight in this case, so return EINA_TRUE */ + return EINA_FALSE; + } + + if (page_info->highlighted == EINA_FALSE) { + _D("Highlight is not exists"); + return EINA_FALSE; + } + + if (widget_viewer_evas_is_faulted(page_info->item)) { + _D("Activate Widget\n"); + widget_viewer_evas_activate_faulted_widget(page_info->item); + } else { + _D("Access action(%s) for focus(%p <> %p) is called", action_type_string(action_info->action_type), focus, page_info->focus); + send_access_event(page_info->item, action_info, 1, _widget_access_action_ret_cb, page); + /* Highligh off and then reset highlight from return callback _widget_access_action_ret_cb() */ + } + + return EINA_TRUE; +} + + + +static Eina_Bool _access_action_scroll_cb(void *data, Evas_Object *focus, Elm_Access_Action_Info *action_info) +{ + Evas_Object *page = data; + page_info_s *page_info; + int must = 0; + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + if (!page_info) { + _E("Page info is not valid\n"); + /* Do not change the highlight in this case, so return EINA_TRUE */ + return EINA_FALSE; + } + + if (page_info->highlighted == EINA_FALSE) { + _D("Highlight is not exists"); + return EINA_FALSE; + } + + if (action_info->mouse_type == 0) { // MOUSE_DOWN + s_info.is_scrolling = EINA_TRUE; + page_info->is_scrolled_object = EINA_TRUE; + must = 1; + } else if (action_info->mouse_type == 2) { // MOUSE_UP + s_info.is_scrolling = EINA_FALSE; + + if (!page_info->is_scrolled_object) { + return EINA_FALSE; + } + + page_info->is_scrolled_object = EINA_FALSE; + must = 1; + } else if (s_info.is_scrolling != EINA_TRUE) { + return EINA_FALSE; + } + + if (widget_viewer_evas_is_faulted(page_info->item)) { + _D("Faulted box, do not send any events"); + return EINA_FALSE; + } + + send_access_event(page_info->item, action_info, must, widget_pended_event_consumer, NULL); + + /* Highligh off and then reset highlight from return callback _widget_access_action_ret_cb() */ + return EINA_FALSE; +} + + + +static Eina_Bool delayed_faulted_action_cb(void *data) +{ + Evas_Object *page = data; + page_info_s *page_info; + Elm_Access_Action_Info action_info; + int ret = ECORE_CALLBACK_RENEW; + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + if (!page_info) { + return ECORE_CALLBACK_CANCEL; + } + + memset(&action_info, 0, sizeof(action_info)); + + if ((int)evas_object_data_get(page, TAG_FAULT_HL) == 1) { + action_info.action_type = ELM_ACCESS_ACTION_HIGHLIGHT; + /** + * Call elm_access_action with "HIGHLIGHT", will invoke the ELM_ACCESS_ACTION_READ callback. + * It will invoke the _access_action_forward_cb, + */ + elm_access_action(page_info->focus, action_info.action_type, &action_info); + + evas_object_data_del(page, TAG_FAULT_HL); + page_info->faulted_hl_timer = NULL; + ret = ECORE_CALLBACK_CANCEL; + } else if ((int)evas_object_data_get(page, TAG_FAULT_HL) == 0) { + action_info.action_type = ELM_ACCESS_ACTION_UNHIGHLIGHT; + elm_access_action(page_info->focus, action_info.action_type, &action_info); + + evas_object_data_set(page, TAG_FAULT_HL, (void *)1); + } + + return ret; +} + + + +/** + * ELM_ACCESS_ACTION_HIGHLIGHT_NEXT + * ELM_ACCESS_ACTION_HIGHLIGHT_PREV + * ELM_ACCESS_ACTION_VALUE_CHANGE + * ELM_ACCESS_ACTION_BACK + * ELM_ACCESS_ACTION_READ + * ELM_ACCESS_ACTION_ENABLE + * ELM_ACCESS_ACTION_DISABLE + */ +static Eina_Bool _access_action_forward_cb(void *data, Evas_Object *focus, Elm_Access_Action_Info *action_info) +{ + Evas_Object *page = data; + page_info_s *page_info; + Evas_Coord x, y; + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + if (!page_info) { + _E("Page info is not valid\n"); + /* Do not change the highlight in this case, so return EINA_TRUE */ + return EINA_FALSE; + } + + if (page_info->highlighted == EINA_FALSE) { + _D("Highlight is not exists"); + return EINA_FALSE; + } + + evas_object_geometry_get(page_info->item, &x, &y, NULL, NULL); + + if (s_info.is_scrolling || x || y) { + _D("I don't want to do anything! %dx%d", x, y); + return EINA_FALSE; + } + + if (widget_viewer_evas_is_faulted(page_info->item)) { + switch (action_info->action_type) { + case ELM_ACCESS_ACTION_READ: + break; + case ELM_ACCESS_ACTION_HIGHLIGHT_NEXT: + case ELM_ACCESS_ACTION_HIGHLIGHT_PREV: + if (!page_info->faulted_hl_timer) { + page_info->faulted_hl_timer = ecore_timer_add(FAULTED_HL_TIMER, delayed_faulted_action_cb, page); + if (!page_info->faulted_hl_timer) { + _E("Faulted box, faulted timer failed"); + } else { + _D("Faulted box, Add highlight emulate timer"); + } + } else { + _D("Faulted box, Keep highlight emulate timer"); + } + break; + default: + break; + } + page_info->need_to_read = EINA_TRUE; + + return EINA_TRUE; + } + + _D("Access action(%s) for focus(%p <> %p) is called, by(%d)", action_type_string(action_info->action_type), focus, page_info->focus, action_info->action_by); + send_access_event(page_info->item, action_info, 1, _widget_access_action_ret_cb, page); + + /* Highligh off and then reset highlight from return callback _widget_access_action_ret_cb() */ + return EINA_TRUE; +} + + + +static Eina_Bool _access_action_mouse_cb(void *data, Evas_Object *focus, Elm_Access_Action_Info *action_info) +{ + Evas_Object *page = data; + page_info_s *page_info; + int must; + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + if (!page_info) { + _E("Page info is not valid\n"); + /* Do not change the highlight in this case, so return EINA_TRUE */ + return EINA_FALSE; + } + + if (page_info->highlighted == EINA_FALSE) { + _D("Highlight is not exists"); + return EINA_FALSE; + } + + if (widget_viewer_evas_is_faulted(page_info->item)) { + _D("Faulted box, do not send any events"); + return EINA_FALSE; + } + + if (s_info.is_scrolling) { + _D("I don't want to do anything!"); + return EINA_FALSE; + } + + must = action_info->mouse_type != 1; + + _D("Access action(%s) for focus(%p <> %p) is called", action_type_string(action_info->action_type), focus, page_info->focus); + send_access_event(page_info->item, action_info, must, widget_pended_event_consumer, NULL); + + /* Highligh off and then reset highlight from return callback _widget_access_action_ret_cb() */ + return EINA_TRUE; +} + + + +static char *_access_widget_read_cb(void *data, Evas_Object *obj) +{ + Evas_Object *page = data; + page_info_s *page_info = NULL; + char *tmp; + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + retv_if(!page_info, NULL); + + if (widget_viewer_evas_is_widget(page_get_item(page)) == 1) { + if (page_info->need_to_read == EINA_FALSE) { + /* + * need_to_read will be toggled by _access_page_num_cb function + * so this function should not touch it. + */ + return NULL; + } + + if (page_info->need_to_unhighlight == EINA_TRUE) { + return NULL; + } + } + + tmp = strdup(_("IDS_IDLE_HEADER_WIDGET")); + retv_if(!tmp, NULL); + return tmp; +} + + +static char *_access_page_name_cb(void *data, Evas_Object *obj) +{ + Evas_Object *page = data; + page_info_s *page_info = NULL; + char *title; + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + retv_if(!page_info, NULL); + + if (widget_viewer_evas_is_widget(page_get_item(page)) == 1) { + if (page_info->need_to_read == EINA_FALSE) { + /* + * need_to_read will be toggled by _access_page_num_cb function + * so this function should not touch it. + */ + return NULL; + } + + if (page_info->need_to_unhighlight == EINA_TRUE) { + return NULL; + } + } + + if (page_info->title) { + title = strdup(page_info->title); + retv_if(!title, NULL); + return title; + } + + /* EFL will free this title. */ + title = page_read_title(page); + retv_if(!title, NULL); + + return title; +} + + + +static char *_access_context_info_cb(void *data, Evas_Object *obj) +{ + Evas_Object *page = data; + page_info_s *page_info = NULL; + char *ctx = NULL; + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + retv_if(!page_info, NULL); + + if (widget_viewer_evas_is_faulted(page_info->item)) { + if (page_info->need_to_read == EINA_FALSE) { + return NULL; + } + + if (page_info->need_to_unhighlight == EINA_TRUE) { + return NULL; + } + page_info->need_to_read = EINA_FALSE; + ctx = strdup(_("IDS_HS_BODY_UNABLE_TO_LOAD_DATA_TAP_TO_RETRY")); + } + + return ctx; +} + + + +HAPI void widget_add_callback(Evas_Object *widget, Evas_Object *page) +{ + page_info_s *page_info = NULL; + + ret_if(!widget); + ret_if(!page); + + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + ret_if(!page_info); + + /* Only handling the focus set operation to page_focus */ + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_HIGHLIGHT, _highlight_action_cb, page); + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_UNHIGHLIGHT, _unhighlight_action_cb, page); + + /* Deliever events to the widget */ + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_HIGHLIGHT_NEXT, _access_action_forward_cb, page); + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_HIGHLIGHT_PREV, _access_action_forward_cb, page); + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_VALUE_CHANGE, _access_action_forward_cb, page); + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_BACK, _access_action_forward_cb, page); + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_READ, _access_action_forward_cb, page); + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_ENABLE, _access_action_forward_cb, page); + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_DISABLE, _access_action_forward_cb, page); + + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_ACTIVATE, _access_action_activate_cb, page); + + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_SCROLL, _access_action_scroll_cb, page); + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_MOUSE, _access_action_mouse_cb, page); + elm_access_action_cb_set(page_info->focus, ELM_ACCESS_ACTION_OVER, _access_action_mouse_cb, page); + + elm_access_info_cb_set(page_info->focus, ELM_ACCESS_INFO, _access_page_name_cb, page); + elm_access_info_cb_set(page_info->focus, ELM_ACCESS_TYPE, _access_widget_read_cb, page); + elm_access_info_cb_set(page_info->focus, ELM_ACCESS_CONTEXT_INFO, _access_context_info_cb, page); + + evas_object_smart_callback_add(widget, WIDGET_SMART_SIGNAL_EXTRA_INFO_UPDATED, _widget_extra_updated_cb, page); + evas_object_smart_callback_add(widget, WIDGET_SMART_SIGNAL_WIDGET_DELETED, _widget_deleted_cb, page); + evas_object_smart_callback_add(widget, WIDGET_SMART_SIGNAL_WIDGET_FAULTED, _widget_faulted_cb, page); + evas_object_smart_callback_add(widget, WIDGET_SMART_SIGNAL_PERIOD_CHANGED, _widget_period_changed_cb, page); + evas_object_smart_callback_add(widget, WIDGET_SMART_SIGNAL_WIDGET_CREATE_ABORTED, _widget_create_aborted_cb, page); +} + + + +HAPI void widget_del_callback(Evas_Object *widget) +{ + ret_if(!widget); + + evas_object_smart_callback_del(widget, WIDGET_SMART_SIGNAL_EXTRA_INFO_UPDATED, _widget_extra_updated_cb); + evas_object_smart_callback_del(widget, WIDGET_SMART_SIGNAL_WIDGET_DELETED, _widget_deleted_cb); + evas_object_smart_callback_del(widget, WIDGET_SMART_SIGNAL_WIDGET_FAULTED, _widget_faulted_cb); + evas_object_smart_callback_del(widget, WIDGET_SMART_SIGNAL_PERIOD_CHANGED, _widget_period_changed_cb); + evas_object_smart_callback_del(widget, WIDGET_SMART_SIGNAL_WIDGET_CREATE_ABORTED, _widget_create_aborted_cb); +} + + + +HAPI void widget_set_update_callback(Evas_Object *obj, int (*updated)(Evas_Object *obj)) +{ + evas_object_data_set(obj, TAG_UPDATED, updated); +} + + + +HAPI void widget_set_scroll_callback(Evas_Object *obj, int (*scroll)(Evas_Object *obj, int hold)) +{ + evas_object_data_set(obj, TAG_SCROLL, scroll); +} + + + +static int uninstall_cb(const char *pkgname, enum pkgmgr_status status, double value, void *data) +{ + layout_info_s *layout_info; + scroller_info_s *scroller_info; + page_info_s *page_info; + Eina_List *page_list; + Evas_Object *page; + + if (status != PKGMGR_STATUS_START) { + return 0; + } + + if (!main_get_info()->layout) { + return 0; + } + + layout_info = evas_object_data_get(main_get_info()->layout, DATA_KEY_LAYOUT_INFO); + if (!layout_info) { + return 0; + } + + scroller_info = evas_object_data_get(layout_info->scroller, DATA_KEY_SCROLLER_INFO); + if (!scroller_info) { + return 0; + } + + if (!scroller_info->box) { + return 0; + } + + page_list = elm_box_children_get(scroller_info->box); + EINA_LIST_FREE(page_list, page) { + page_info = evas_object_data_get(page, DATA_KEY_PAGE_INFO); + if (!page_info) { + continue; + } + + if (page_info->direction != PAGE_DIRECTION_RIGHT) { + continue; + } + + if (!page_info->item) { + continue; + } + + if (!widget_viewer_evas_is_faulted(page_info->item)) { + continue; + } + + _D("Faulted package: %s", widget_viewer_evas_get_widget_id(page_info->item)); + _widget_remove(page); + } + + return 0; +} + + + +HAPI void widget_init(Evas_Object *win) +{ + int val; + + add_viewer_pkgmgr_add_event_callback(PKGMGR_EVENT_UNINSTALL, uninstall_cb, NULL); + + widget_viewer_evas_set_option(WIDGET_VIEWER_EVAS_AUTO_RENDER_SELECTION, 1); + + if (preference_get_int("memory/private/org.tizen.w-home/auto_feed", &val) >= 0) { + widget_viewer_evas_set_option(WIDGET_VIEWER_EVAS_EVENT_AUTO_FEED, val); + } + + if (preference_get_int("memory/private/org.tizen.w-home/sensitive_move", &val) >= 0) { + widget_viewer_evas_set_option(WIDGET_VIEWER_EVAS_SENSITIVE_MOVE, val); + } + + widget_viewer_evas_init(win); + widget_viewer_evas_set_option(WIDGET_VIEWER_EVAS_SCROLL_X, 1); +} + + + +HAPI void widget_fini(void) +{ + widget_viewer_evas_fini(); + add_viewer_pkgmgr_del_event_callback(PKGMGR_EVENT_UNINSTALL, uninstall_cb, NULL); +} + + + +// End of a file |