diff options
author | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 01:38:12 +0900 |
---|---|---|
committer | Jinkun Jang <jinkun.jang@samsung.com> | 2013-03-13 01:38:12 +0900 |
commit | 7c83e9661e76a4297913256f65d84709c9c3e26e (patch) | |
tree | 7f76d9983beab3974ec626e29f8b30fd969778ce /daemon | |
parent | d122c66eb003810833ffc2c9e7ba275c48ef5b95 (diff) | |
download | quickpanel-7c83e9661e76a4297913256f65d84709c9c3e26e.tar.gz quickpanel-7c83e9661e76a4297913256f65d84709c9c3e26e.tar.bz2 quickpanel-7c83e9661e76a4297913256f65d84709c9c3e26e.zip |
Tizen 2.1 base
Diffstat (limited to 'daemon')
-rwxr-xr-x | daemon/common.h | 113 | ||||
-rwxr-xr-x | daemon/idletxt/idletxt.c | 537 | ||||
-rwxr-xr-x | daemon/list_util.c | 391 | ||||
-rwxr-xr-x | daemon/list_util.h | 81 | ||||
-rwxr-xr-x | daemon/minictrl/minictrl.c | 457 | ||||
-rwxr-xr-x | daemon/modules.c | 197 | ||||
-rwxr-xr-x | daemon/modules.h | 34 | ||||
-rwxr-xr-x | daemon/notifications/brightness.c | 464 | ||||
-rwxr-xr-x | daemon/notifications/noti.c | 1999 | ||||
-rwxr-xr-x | daemon/notifications/noti.h | 20 | ||||
-rwxr-xr-x | daemon/notifications/noti_box.c | 480 | ||||
-rwxr-xr-x | daemon/notifications/noti_box.h | 46 | ||||
-rwxr-xr-x | daemon/notifications/noti_display_app.c | 422 | ||||
-rwxr-xr-x | daemon/notifications/noti_display_app.h | 28 | ||||
-rwxr-xr-x | daemon/notifications/noti_gridbox.c | 454 | ||||
-rwxr-xr-x | daemon/notifications/noti_gridbox.h | 34 | ||||
-rwxr-xr-x | daemon/notifications/noti_node.c | 146 | ||||
-rwxr-xr-x | daemon/notifications/noti_node.h | 41 | ||||
-rwxr-xr-x | daemon/notifications/noti_win.c | 314 | ||||
-rwxr-xr-x | daemon/notifications/noti_win.h | 41 | ||||
-rwxr-xr-x | daemon/notifications/status_msg.c | 315 | ||||
-rwxr-xr-x | daemon/notifications/ticker.c | 726 | ||||
-rwxr-xr-x | daemon/quickpanel-ui.c | 1156 | ||||
-rwxr-xr-x | daemon/quickpanel-ui.h | 123 |
24 files changed, 8619 insertions, 0 deletions
diff --git a/daemon/common.h b/daemon/common.h new file mode 100755 index 0000000..79ffbb1 --- /dev/null +++ b/daemon/common.h @@ -0,0 +1,113 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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. + */ + +#ifndef __QP_COMMON_H_ +#define __QP_COMMON_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include "quickpanel_debug_util.h" + +#define QP_OK (0) +#define QP_FAIL (-1) + +#ifdef _DLOG_USED +#define LOG_TAG "quickpanel" +#include <dlog.h> + +#define DBG(fmt , args...) \ + do { \ + LOGD("[%s : %d] "fmt"\n", __func__, __LINE__, ##args); \ + } while (0) + +#define INFO(fmt , args...) \ + do { \ + LOGI("[%s : %d] "fmt"\n", __func__, __LINE__, ##args); \ + } while (0) + +#define WARN(fmt , args...) \ + do { \ + LOGI("[%s : %d] "fmt"\n", __func__, __LINE__, ##args); \ + } while (0) + +#define ERR(fmt , args...) \ + do { \ + LOGI("[%s : %d] "fmt"\n", __func__, __LINE__, ##args); \ + } while (0) + +#elif FILE_DEBUG /*_DLOG_USED*/ +#define DBG(fmt , args...) \ + do { \ + debug_printf("[D]%s : %d] "fmt"\n", \ + __func__, __LINE__, ##args); \ + } while (0) + +#define INFO(fmt , args...) \ + do { \ + debug_printf("[I][%s : %d] "fmt"\n",\ + __func__, __LINE__, ##args); \ + } while (0) + +#define WARN(fmt , args...) \ + do { \ + debug_printf("[W][%s : %d] "fmt"\n", \ + __func__, __LINE__, ##args); \ + } while (0) + +#define ERR(fmt , args...) \ + do { \ + debug_printf("[E][%s : %d] "fmt"\n", \ + __func__, __LINE__, ##args); \ + } while (0) + +#else /*_DLOG_USED*/ +#define DBG(fmt , args...) \ + do { \ + fprintf("[D][%s : %d] "fmt"\n", __func__, __LINE__, ##args); \ + } while (0) + +#define INFO(fmt , args...) \ + do { \ + fprintf("[I][%s : %d] "fmt"\n", __func__, __LINE__, ##args); \ + } while (0) + +#define WARN(fmt , args...) \ + do { \ + fprintf("[W][%s : %d] "fmt"\n", __func__, __LINE__, ##args); \ + } while (0) + +#define ERR(fmt , args...) \ + do { \ + fprintf("[E][%s : %d] "fmt"\n", __func__, __LINE__, ##args); \ + } while (0) +#endif /*_DLOG_USED*/ + +#define retif(cond, ret, str, args...) do { \ + if (cond) { \ + WARN(str, ##args);\ + return ret;\ + } \ +} while (0); + +#define gotoif(cond, target, str, args...) do { \ + if (cond) { \ + WARN(str, ##args); \ + goto target; \ + } \ +} while (0); + +#endif /* __QP_COMMON_H_ */ diff --git a/daemon/idletxt/idletxt.c b/daemon/idletxt/idletxt.c new file mode 100755 index 0000000..0b4c72e --- /dev/null +++ b/daemon/idletxt/idletxt.c @@ -0,0 +1,537 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <Ecore_X.h> +#include <vconf.h> +#include "common.h" +#include "quickpanel-ui.h" + +#define QP_IDLETXT_PART "qp.noti.swallow.spn" + +#define QP_SPN_BASE_PART "qp.base.spn.swallow" +#define QP_SPN_BOX_PART "qp.spn.swallow" +#define QP_BUTTON_PART "qp.button.swallow" + +#define QP_IDLETXT_MAX_KEY 4 +#define QP_IDLETXT_MAX_LEN 1024 +#define QP_IDLETXT_SLIDE_LEN 130 + +#define QP_IDLETXT_LABEL_STRING \ + "<font_size=36 font=Tizen:style=Medium><color=#959494FF><align=left>%s</align>" \ + "</color></font_size>" + +static int quickpanel_idletxt_init(void *data); +static int quickpanel_idletxt_fini(void *data); +static int quickpanel_idletxt_suspend(void *data); +static int quickpanel_idletxt_resume(void *data); +static void quickpanel_idletxt_lang_changed(void *data); + +QP_Module idletxt = { + .name = "idletxt", + .init = quickpanel_idletxt_init, + .fini = quickpanel_idletxt_fini, + .suspend = quickpanel_idletxt_suspend, + .resume = quickpanel_idletxt_resume, + .lang_changed = quickpanel_idletxt_lang_changed +}; + +static int _quickpanel_idletxt_map_exceptional_nwname(char *txt, char *map_txt, int map_txt_len) +{ + int is_mapped = 0; + + if (txt == NULL || map_txt == NULL) { + return is_mapped; + } + + if (strncasecmp(txt, "No Service", strlen("No Service")) == 0) { + strncpy(map_txt, _S("IDS_COM_BODY_NO_SERVICE"), map_txt_len); + is_mapped = 1; + } else if (strncasecmp(txt, "EMERGENCY", strlen("EMERGENCY")) == 0) { + strncpy(map_txt, _("IDS_CALL_POP_CALLING_EMERG_ONLY"), map_txt_len); + is_mapped = 1; + } else if (strncasecmp(txt, "Searching", strlen("Searching")) == 0) { + strncpy(map_txt, _S("IDS_COM_BODY_SEARCHING"), map_txt_len); + is_mapped = 1; + } else if (strncasecmp(txt, "SIM Error", strlen("SIM Error")) == 0) { + strncpy(map_txt, _S("IDS_COM_BODY_INVALID_SIM_CARD"), map_txt_len); + is_mapped = 1; + } else if (strncasecmp(txt, "NO SIM", strlen("NO SIM")) == 0) { + strncpy(map_txt, _S("IDS_COM_BODY_NO_SIM"), map_txt_len); + is_mapped = 1; + } + + return is_mapped; +} + +static Evas_Object *_quickpanel_idletxt_create_label(Evas_Object * parent, + char *txt) +{ + Evas_Object *obj = NULL; + char buf[QP_IDLETXT_MAX_LEN] = { 0, }; + char localized_txt[QP_IDLETXT_MAX_LEN] = { 0, }; + int len = 0; + + retif(parent == NULL || txt == NULL, NULL, "Invalid parameter!"); + + memset(buf, 0x00, sizeof(buf)); + + if (_quickpanel_idletxt_map_exceptional_nwname(txt, localized_txt, QP_IDLETXT_MAX_LEN) == 1) { + len = snprintf(buf, sizeof(buf), QP_IDLETXT_LABEL_STRING, localized_txt); + } else { + len = snprintf(buf, sizeof(buf), QP_IDLETXT_LABEL_STRING, txt); + } + + retif(len < 0, NULL, "len < 0"); + + obj = elm_label_add(parent); + if (obj != NULL) { + elm_object_text_set(obj, buf); + + evas_object_size_hint_weight_set(obj, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(obj, EVAS_HINT_FILL, 0.5); + + evas_object_show(obj); + } + + return obj; +} + +static Evas_Object *_quickpanel_idletxt_create_box(Evas_Object * parent) +{ + Evas_Object *box = NULL; + + retif(parent == NULL, NULL, "Invalid parameter!"); + + box = elm_box_add(parent); + if (box != NULL) { + elm_box_horizontal_set(box, EINA_FALSE); + + evas_object_show(box); + } + + return box; +} + +static int _quickpanel_idletxt_get_txt(const char *key, char *txt, int size) +{ + int len = 0; + char *str = NULL; + int i = 0; + + str = vconf_get_str(key); + if (str == NULL || str[0] == '\0') + return 0; + + /* check ASCII code */ + for (i = strlen(str) - 1; i >= 0; i--) { + if (str[i] <= 31 || str[i] >= 127) + goto failed; + } + + len = snprintf(txt, size, "%s", str); + + failed: + if (str) + free(str); + + return len; +} + +static Evas_Object *_quickpanel_idletxt_add_label(Evas_Object * box, + char *key[]) +{ + char txt[QP_IDLETXT_MAX_LEN] = { 0, }; + char buf[QP_IDLETXT_MAX_LEN] = { 0, }; + int len = 0; + int i = 0; + Evas_Object *obj = NULL; + + retif(key == NULL || key[0] == '\0', NULL, "Invalid parameter!"); + + memset(txt, 0x00, sizeof(txt)); + + for (i = 0; key[i]; i++) { + memset(buf, 0x00, sizeof(buf)); + + /* get next key string */ + if (_quickpanel_idletxt_get_txt(key[i], buf, sizeof(buf))) { + INFO("VCONFKEY(%s) = %s", key[i], buf); + + len = strlen(txt); + + snprintf(&txt[len], sizeof(txt) - len, "%s%s", + len ? " - " : "", buf); + } + } + + len = strlen(txt); + + if (len) { + obj = _quickpanel_idletxt_create_label(box, txt); + + if (obj != NULL) { + if (len > QP_IDLETXT_SLIDE_LEN) + elm_label_slide_set(obj, EINA_TRUE); + + return obj; + } + } + + return NULL; +} + +static Evas_Object *_quickpanel_idletxt_exception_add_label(Evas_Object * box) +{ + int service_type = VCONFKEY_TELEPHONY_SVCTYPE_SEARCH; + char *text = NULL; + Evas_Object *obj = NULL; + + if (vconf_get_int(VCONFKEY_TELEPHONY_SVCTYPE, &service_type) != 0) { + DBG("fail to get VCONFKEY_TELEPHONY_SVCTYPE"); + } + + switch(service_type) { + case VCONFKEY_TELEPHONY_SVCTYPE_NOSVC: + text = _S("IDS_COM_BODY_NO_SERVICE"); + break; + case VCONFKEY_TELEPHONY_SVCTYPE_EMERGENCY: + text = _("IDS_CALL_POP_CALLING_EMERG_ONLY"); + break; + default: + if (service_type > VCONFKEY_TELEPHONY_SVCTYPE_SEARCH) { + text = vconf_get_str(VCONFKEY_TELEPHONY_NWNAME); + } else { + text = _S("IDS_COM_BODY_SEARCHING"); + } + break; + } + + if (text != NULL) { + obj = _quickpanel_idletxt_create_label(box, text); + + if (obj != NULL) { + if (strlen(text) > QP_IDLETXT_SLIDE_LEN) + elm_label_slide_set(obj, EINA_TRUE); + + return obj; + } + } + + return NULL; +} + +static Evas_Object *_quickpanel_idletxt_get_spn(Evas_Object * box) +{ + Evas_Object *label = NULL; + char *keylist[QP_IDLETXT_MAX_KEY] = { 0, }; + int ret = 0; + int state = 0; + int i = 0; + int service_type = VCONFKEY_TELEPHONY_SVCTYPE_NONE; + + /* make keylist */ + if (vconf_get_int(VCONFKEY_TELEPHONY_SVCTYPE, &service_type) != 0) { + DBG("fail to get VCONFKEY_TELEPHONY_SVCTYPE"); + } + + ret = vconf_get_int(VCONFKEY_TELEPHONY_SPN_DISP_CONDITION, &state); + if (ret == 0) { + INFO("VCONFKEY(%s) = %d", + VCONFKEY_TELEPHONY_SPN_DISP_CONDITION, state); + + if (state != VCONFKEY_TELEPHONY_DISP_INVALID + && service_type > VCONFKEY_TELEPHONY_SVCTYPE_SEARCH) { + if (i < QP_IDLETXT_MAX_KEY) { + if (state & VCONFKEY_TELEPHONY_DISP_SPN) { + keylist[i++] = + strdup(VCONFKEY_TELEPHONY_SPN_NAME); + } + + if (state & VCONFKEY_TELEPHONY_DISP_PLMN) { + keylist[i++] = + strdup(VCONFKEY_TELEPHONY_NWNAME); + } + } + + if (i > 0) { + /* get string with keylist */ + label = _quickpanel_idletxt_add_label(box, keylist); + + /* free keylist */ + while (i > 0) { + if (keylist[i]) + free(keylist[i]); + + i--; + } + } + } else { + label = _quickpanel_idletxt_exception_add_label(box); + } + } + + return label; +} + +static Evas_Object *_quickpanel_idletxt_get_sat_text(Evas_Object * box) +{ + Evas_Object *label = NULL; + char *keylist[] = { VCONFKEY_SAT_IDLE_TEXT, 0 }; + + /* get string with keylist */ + label = _quickpanel_idletxt_add_label(box, keylist); + + return label; +} + +static void _quickpanel_idletxt_button_clicked(void *data, Evas_Object * obj, void *event_info) +{ + struct appdata *ad = data; + retif(obj == NULL, , "Invalid parameter!"); + retif(ad == NULL, , "Invalid parameter!"); + retif(ad->win == NULL, , "ad->win is NULL"); + + Ecore_X_Window zone; + + if (ad->is_emul == 1) + quickpanel_launch_app(QP_SETTING_PKG_SETTING_EMUL, NULL); + else + quickpanel_launch_app(QP_SETTING_PKG_SETTING, NULL); + + zone = ecore_x_e_illume_zone_get(elm_win_xwindow_get(ad->win)); + ecore_x_e_illume_quickpanel_state_send(zone, + ECORE_X_ILLUME_QUICKPANEL_STATE_OFF); + + elm_object_signal_emit(obj, "elm,action,button,reset", "elm"); +} + +static void quickpanel_idletxt_update(void *data) +{ + struct appdata *ad = NULL; + Evas_Object *label = NULL; + Evas_Object *idletxtbox = NULL; + Evas_Object *button_settings = NULL; + Evas_Object *spn = NULL; + + retif(!data, , "Invalid parameter!"); + ad = data; + + retif(!ad->ly, , "layout is NULL!"); + + spn = elm_object_part_content_get(ad->ly, QP_SPN_BASE_PART); + retif(!spn, , "spn layout is NULL!"); + + idletxtbox = elm_object_part_content_get(spn, QP_SPN_BOX_PART); + button_settings = elm_object_part_content_get(spn, QP_BUTTON_PART); + + if (idletxtbox == NULL) { + idletxtbox = _quickpanel_idletxt_create_box(spn); + retif(idletxtbox == NULL, , "Failed to create box!"); + elm_object_part_content_set(spn, + QP_SPN_BOX_PART, idletxtbox); + } + + elm_box_clear(idletxtbox); + + /* get spn */ + label = _quickpanel_idletxt_get_spn(idletxtbox); + if (label != NULL) + elm_box_pack_end(idletxtbox, label); + + /* get sat idle text */ + label = _quickpanel_idletxt_get_sat_text(idletxtbox); + if (label != NULL) + elm_box_pack_end(idletxtbox, label); + + if (button_settings == NULL) { + button_settings = elm_button_add(spn); + retif(button_settings == NULL, , "Failed to create clear button!"); + elm_object_style_set(button_settings, "quickpanel_standard"); + elm_object_part_content_set(spn, + QP_BUTTON_PART, button_settings); + evas_object_smart_callback_add(button_settings, "clicked", + _quickpanel_idletxt_button_clicked, ad); + } + + elm_object_text_set(button_settings, _S("IDS_COM_BODY_SETTINGS")); +} + +static void quickpanel_idletxt_changed_cb(keynode_t *node, void *data) +{ + quickpanel_idletxt_update(data); +} + +static int _quickpanel_idletxt_register_event_handler(void *data) +{ + int ret = 0; + + ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SVCTYPE, + quickpanel_idletxt_changed_cb, data); + if (ret != 0) + ERR("Failed to register [%s]", + VCONFKEY_TELEPHONY_SVCTYPE); + + ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SPN_DISP_CONDITION, + quickpanel_idletxt_changed_cb, data); + if (ret != 0) + ERR("Failed to register [%s]", + VCONFKEY_TELEPHONY_SPN_DISP_CONDITION); + + ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SPN_NAME, + quickpanel_idletxt_changed_cb, data); + if (ret != 0) + ERR("Failed to register [%s]", + VCONFKEY_TELEPHONY_SPN_NAME); + + + ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_NWNAME, + quickpanel_idletxt_changed_cb, data); + if (ret != 0) + ERR("Failed to register [%s]", + VCONFKEY_TELEPHONY_NWNAME); + + ret = vconf_notify_key_changed(VCONFKEY_SAT_IDLE_TEXT, + quickpanel_idletxt_changed_cb, data); + if (ret != 0) + ERR("Failed to register [%s]", + VCONFKEY_SAT_IDLE_TEXT); + + + return QP_OK; +} + +static int _quickpanel_idletxt_unregister_event_handler(void) +{ + int ret = 0; + + ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SVCTYPE, + quickpanel_idletxt_changed_cb); + if (ret != 0) + ERR("Failed to unregister [%s]", + VCONFKEY_TELEPHONY_SVCTYPE); + + ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SPN_DISP_CONDITION, + quickpanel_idletxt_changed_cb); + if (ret != 0) + ERR("Failed to unregister [%s]", + VCONFKEY_TELEPHONY_SPN_DISP_CONDITION); + + ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SPN_NAME, + quickpanel_idletxt_changed_cb); + if (ret != 0) + ERR("Failed to unregister [%s]", + VCONFKEY_TELEPHONY_SPN_NAME); + + + ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NWNAME, + quickpanel_idletxt_changed_cb); + if (ret != 0) + ERR("Failed to unregister [%s]", + VCONFKEY_TELEPHONY_NWNAME); + + ret = vconf_ignore_key_changed(VCONFKEY_SAT_IDLE_TEXT, + quickpanel_idletxt_changed_cb); + if (ret != 0) + ERR("Failed to unregister [%s]", + VCONFKEY_SAT_IDLE_TEXT); + + return QP_OK; +} + +static Evas_Object *_idletxt_load_edj(Evas_Object * parent, const char *file, + const char *group) +{ + Eina_Bool r; + Evas_Object *eo = NULL; + + retif(parent == NULL, NULL, "Invalid parameter!"); + + eo = elm_layout_add(parent); + retif(eo == NULL, NULL, "Failed to add layout object!"); + + r = elm_layout_file_set(eo, file, group); + retif(r != EINA_TRUE, NULL, "Failed to set edje object file!"); + + evas_object_size_hint_weight_set(eo, + EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_show(eo); + + return eo; +} + +static int quickpanel_idletxt_init(void *data) +{ + struct appdata *ad = NULL; + Evas_Object *spn = NULL; + + retif(!data, QP_FAIL, "Invalid parameter!"); + ad = data; + + spn = _idletxt_load_edj(ad->ly, DEFAULT_EDJ, "quickpanel/spn"); + retif(!spn, QP_FAIL, "fail to load spn layout"); + + elm_object_part_content_set(ad->ly, QP_SPN_BASE_PART, spn); + + quickpanel_idletxt_update(data); + + _quickpanel_idletxt_register_event_handler(data); + + return QP_OK; +} + +static int quickpanel_idletxt_fini(void *data) +{ + struct appdata *ad = (struct appdata *)data; + Evas_Object *spn = NULL; + Evas_Object *idletxtbox = NULL; + + retif(ad == NULL, QP_FAIL, "Invalid parameter!"); + + _quickpanel_idletxt_unregister_event_handler(); + + retif(!ad->ly, QP_FAIL, "Invalid parameter!"); + + spn = elm_object_part_content_unset(ad->ly, QP_SPN_BASE_PART); + retif(!spn, QP_OK, "spn is NULL"); + + idletxtbox = elm_object_part_content_get(spn, QP_SPN_BOX_PART); + if (idletxtbox) { + elm_object_part_content_unset(spn, QP_SPN_BOX_PART); + evas_object_del(idletxtbox); + } + + evas_object_del(spn); + + return QP_OK; +} + +static int quickpanel_idletxt_suspend(void *data) +{ + return QP_OK; +} + +static int quickpanel_idletxt_resume(void *data) +{ + return QP_OK; +} + +static void quickpanel_idletxt_lang_changed(void *data) +{ + retif(data == NULL, , "Invalid parameter!"); + + quickpanel_idletxt_update(data); +} diff --git a/daemon/list_util.c b/daemon/list_util.c new file mode 100755 index 0000000..a4e5a5e --- /dev/null +++ b/daemon/list_util.c @@ -0,0 +1,391 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <stdlib.h> + +#include "common.h" +#include "list_util.h" + +struct _qp_item_data { + qp_item_type_e type; + void *data; +}; + +static qp_item_count g_qp_item_count = { + .group = 0, + .ongoing = 0, + .noti = 0, + .minicontrol = 0, +}; + +qp_item_data *quickpanel_list_util_item_new(qp_item_type_e type, void *data) +{ + qp_item_data *qid = NULL; + + qid = malloc(sizeof(struct _qp_item_data)); + if (!qid) { + ERR("fail to alloc qid"); + return NULL; + } + + qid->type = type; + qid->data = data; + + return qid; +} + +qp_item_type_e quickpanel_list_util_item_get_item_type(qp_item_data *qid) +{ + qp_item_type_e item_type = QP_ITEM_TYPE_NONE; + + if (!qid) + return QP_ITEM_TYPE_NONE; + + item_type = qid->type; + + return item_type; +} + +void *quickpanel_list_util_item_get_data(qp_item_data *qid) +{ + void *user_data = NULL; + + if (!qid) + return NULL; + + user_data = qid->data; + + return user_data; +} + +void quickpanel_list_util_item_set_data(qp_item_data *qid, void *data) +{ + if (!qid) + return ; + + qid->data = data; +} + +int quickpanel_list_util_item_compare(const void *data1, const void *data2) +{ + int diff = 0; + qp_item_data *qid1 = NULL; + qp_item_data *qid2 = NULL; + const Elm_Object_Item *it1 = data1; + const Elm_Object_Item *it2 = data2; + + if (!it1) { + INFO("it1 is NULL"); + return -1; + } + + if (!it2) { + INFO("it2 is NULL"); + return 1; + } + + qid1 = elm_object_item_data_get(it1); + qid2 = elm_object_item_data_get(it2); + + if (!qid1) { + INFO("qid1 is NULL"); + return -1; + } + + if (!qid2) { + INFO("qid2 is NULL"); + return 1; + } + + /* elm_genlist sort is not working as i expected */ + if (qid1->type == qid2->type) + return 1; + + diff = qid1->type - qid2->type; + return diff; +} + +void quickpanel_list_util_item_del_by_type(Evas_Object *list, + const Elm_Object_Item *refer_item, + qp_item_type_e type) +{ + const Elm_Object_Item *start_item = NULL; + + if (!list) + return; + + if (refer_item) + start_item = refer_item; + else + start_item = elm_genlist_first_item_get(list); + + while (start_item) { + qp_item_data *qid = NULL; + const Elm_Object_Item *next = NULL; + + next = elm_genlist_item_next_get(start_item); + qid = elm_object_item_data_get(start_item); + if (!qid) { + ERR("fail to get qid, continue loop"); + start_item = next; + continue; + } + + if (qid->type > type) + break; + else if (qid->type == type) + elm_object_item_del((Elm_Object_Item *)start_item); + + start_item = next; + } + + return; +} + +void quickpanel_list_util_item_update_by_type(Evas_Object *list, + Elm_Object_Item *refer_item, + qp_item_type_e type) +{ + Elm_Object_Item *start_item = NULL; + + if (!list) + return; + + if (refer_item) + start_item = refer_item; + else + start_item = elm_genlist_first_item_get(list); + + while (start_item) { + qp_item_data *qid = NULL; + Elm_Object_Item *next = NULL; + + next = elm_genlist_item_next_get(start_item); + qid = elm_object_item_data_get(start_item); + if (!qid) { + ERR("fail to get qid, continue loop"); + start_item = next; + continue; + } + + if (qid->type > type) + break; + else if (qid->type == type) { + elm_genlist_item_fields_update(start_item, "*", ELM_GENLIST_ITEM_FIELD_ALL); + } + + start_item = next; + } + + return; +} + +Elm_Object_Item *quickpanel_list_util_find_item_by_type(Evas_Object *list, + void *data, + Elm_Object_Item *refer_item, + qp_item_type_e type) +{ + Elm_Object_Item *start_item = NULL; + Elm_Object_Item *found = NULL; + + if (!list) + return NULL; + + if (refer_item) + start_item = refer_item; + else + start_item = elm_genlist_first_item_get(list); + + while (start_item) { + qp_item_data *qid = NULL; + Elm_Object_Item *next = NULL; + void *user_data = NULL; + + next = elm_genlist_item_next_get(start_item); + qid = elm_object_item_data_get(start_item); + if (!qid) { + ERR("fail to get qid, continue loop"); + start_item = next; + continue; + } + + if (qid->type > type) + break; + else if (qid->type == type) { + user_data = quickpanel_list_util_item_get_data(qid); + if (user_data == data) { + found = start_item; + break; + } + } + + start_item = next; + } + + return found; +} + +static int __item_compare(const void *data1, const void *data2) +{ + int diff = 0; + const Elm_Object_Item *it1 = data1; + const qp_item_data *qid1 = NULL; + const qp_item_data *qid2 = data2; + + if (!data1) { + INFO("data1 is NULL"); + return -1; + } + + if (!data2) { + INFO("data2 is NULL"); + return 1; + } + + qid1 = elm_object_item_data_get(it1); + + if (!qid1) { + INFO("qid1 is NULL"); + return -1; + } + + diff = qid1->type - qid2->type; + + return diff; +} + + +Elm_Object_Item *quickpanel_list_util_sort_insert(Evas_Object *list, + const Elm_Genlist_Item_Class *itc, + const void *item_data, + Elm_Object_Item *parent, + Elm_Genlist_Item_Type type, + Evas_Smart_Cb func, + const void *func_data) +{ + Elm_Object_Item *it = NULL; + Elm_Object_Item *first = NULL; + + retif(!list, NULL, "list is NULL"); + retif(!itc, NULL, "itc is NULL"); + retif(!item_data, NULL, "item_data is NULL"); + + first = elm_genlist_first_item_get(list); + while (first) { + if (__item_compare(first, item_data) >= 0) + break; + + first = elm_genlist_item_next_get(first); + } + + if (!first) + it = elm_genlist_item_append(list, itc, item_data, parent, + type, func, func_data); + else + it = elm_genlist_item_insert_before(list, itc, item_data, + parent, first, type, func, func_data); + + if (it != NULL) { + quickpanel_list_util_add_count((qp_item_data *)item_data); + } + + return it; +} + +qp_item_count *quickpanel_list_util_get_item_count(void) +{ + return &g_qp_item_count; +} + +void quickpanel_list_util_add_count(qp_item_data *qid) +{ + retif(qid == NULL, , "qid is NULL"); + + switch(qid->type) + { + case QP_ITEM_TYPE_ONGOING_NOTI: + g_qp_item_count.ongoing++; + break; + case QP_ITEM_TYPE_NOTI_GROUP: + g_qp_item_count.group++; + break; + case QP_ITEM_TYPE_NOTI: + g_qp_item_count.noti++; + break; + case QP_ITEM_TYPE_MINICTRL_ONGOING: + case QP_ITEM_TYPE_MINICTRL_TOP: + case QP_ITEM_TYPE_MINICTRL_MIDDLE: + case QP_ITEM_TYPE_MINICTRL_LOW: + g_qp_item_count.minicontrol++; + break; + case QP_ITEM_TYPE_NONE: + case QP_ITEM_TYPE_SETTING: + case QP_ITEM_TYPE_TOGGLE: + case QP_ITEM_TYPE_BRIGHTNESS: + case QP_ITEM_TYPE_MAX: + break; + } + + DBG("(type:%d)\nnum_ongoing:%d, num_group:%d, num_noti:%d, num_minicontrol:%d" + , qid->type + , g_qp_item_count.ongoing + , g_qp_item_count.group + , g_qp_item_count.noti + , g_qp_item_count.minicontrol); +} + +void quickpanel_list_util_del_count(qp_item_data *qid) +{ + retif(qid == NULL, , "qid is NULL"); + + quickpanel_list_util_del_count_by_itemtype(qid->type); +} + +void quickpanel_list_util_del_count_by_itemtype(qp_item_type_e type) +{ + switch(type) + { + case QP_ITEM_TYPE_ONGOING_NOTI: + g_qp_item_count.ongoing = (g_qp_item_count.ongoing <= 0) ? 0 : g_qp_item_count.ongoing - 1; + break; + case QP_ITEM_TYPE_NOTI_GROUP: + g_qp_item_count.group = (g_qp_item_count.group <= 0) ? 0 : g_qp_item_count.group - 1; + break; + case QP_ITEM_TYPE_NOTI: + g_qp_item_count.noti = (g_qp_item_count.noti <= 0) ? 0 : g_qp_item_count.noti - 1; + break; + case QP_ITEM_TYPE_MINICTRL_ONGOING: + case QP_ITEM_TYPE_MINICTRL_TOP: + case QP_ITEM_TYPE_MINICTRL_MIDDLE: + case QP_ITEM_TYPE_MINICTRL_LOW: + g_qp_item_count.minicontrol = (g_qp_item_count.minicontrol <= 0) ? 0 : g_qp_item_count.minicontrol - 1; + break; + case QP_ITEM_TYPE_NONE: + case QP_ITEM_TYPE_SETTING: + case QP_ITEM_TYPE_TOGGLE: + case QP_ITEM_TYPE_BRIGHTNESS: + case QP_ITEM_TYPE_MAX: + break; + } + + DBG("(type:%d)\nnum_ongoing:%d, num_group:%d, num_noti:%d, num_minicontrol:%d" + , type + , g_qp_item_count.ongoing + , g_qp_item_count.group + , g_qp_item_count.noti + , g_qp_item_count.minicontrol); +} diff --git a/daemon/list_util.h b/daemon/list_util.h new file mode 100755 index 0000000..902ec2d --- /dev/null +++ b/daemon/list_util.h @@ -0,0 +1,81 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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. + */ + +#ifndef _QP_LIST_UTIL_DEF_ +#define _QP_LIST_UTIL_DEF_ + +#include <Elementary.h> + +typedef enum { + QP_ITEM_TYPE_NONE = -1, + QP_ITEM_TYPE_SETTING = 0, + QP_ITEM_TYPE_TOGGLE, + QP_ITEM_TYPE_BRIGHTNESS, + QP_ITEM_TYPE_ONGOING_NOTI, + QP_ITEM_TYPE_MINICTRL_ONGOING, + QP_ITEM_TYPE_MINICTRL_TOP, + QP_ITEM_TYPE_MINICTRL_MIDDLE, + QP_ITEM_TYPE_MINICTRL_LOW, + QP_ITEM_TYPE_NOTI_GROUP, + QP_ITEM_TYPE_NOTI, + QP_ITEM_TYPE_MAX, +} qp_item_type_e; + +typedef struct _qp_item_data qp_item_data; +typedef struct _qp_item_count { + int group; + int ongoing; + int noti; + int minicontrol; +} qp_item_count; + + +qp_item_data *quickpanel_list_util_item_new(qp_item_type_e type, void *data); + +qp_item_type_e quickpanel_list_util_item_get_item_type(qp_item_data *qid); +void *quickpanel_list_util_item_get_data(qp_item_data *qid); +void quickpanel_list_util_item_set_data(qp_item_data *qid, void *data); + +int quickpanel_list_util_item_compare(const void *data1, const void *data2); + +void quickpanel_list_util_item_del_by_type(Evas_Object *list, + const Elm_Object_Item *refer_item, + qp_item_type_e type); + +void quickpanel_list_util_item_update_by_type(Evas_Object *list, + Elm_Object_Item *refer_item, + qp_item_type_e type); + +Elm_Object_Item *quickpanel_list_util_find_item_by_type(Evas_Object *list, + void *data, + Elm_Object_Item *refer_item, + qp_item_type_e type); + +Elm_Object_Item *quickpanel_list_util_sort_insert(Evas_Object *list, + const Elm_Genlist_Item_Class *itc, + const void *item_data, + Elm_Object_Item *parent, + Elm_Genlist_Item_Type type, + Evas_Smart_Cb func, + const void *func_data); + +qp_item_count *quickpanel_list_util_get_item_count(void); +void quickpanel_list_util_add_count(qp_item_data *qid); +void quickpanel_list_util_del_count(qp_item_data *qid); +void quickpanel_list_util_del_count_by_itemtype(qp_item_type_e type); + +#endif /* _QP_LIST_UTIL_DEF_ */ + diff --git a/daemon/minictrl/minictrl.c b/daemon/minictrl/minictrl.c new file mode 100755 index 0000000..e7c7e74 --- /dev/null +++ b/daemon/minictrl/minictrl.c @@ -0,0 +1,457 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <glib.h> +#include <Ecore_X.h> +#include <minicontrol-viewer.h> +#include <minicontrol-monitor.h> +#include <string.h> +#include "common.h" +#include "quickpanel-ui.h" +#include "list_util.h" +#include "quickpanel_debug_util.h" + +#define QP_R_MARGIN 12 +#define MINICONTROL_WIDTH_P_MAX 692 +#define MINICONTROL_WIDTH_L_MAX 1252 + +#define MINICONTROL_TYPE_STR_ONGOING "_ongoing]" + +static int quickpanel_minictrl_init(void *data); +static int quickpanel_minictrl_fini(void *data); +static unsigned int quickpanel_minictrl_get_height(void *data); + +QP_Module minictrl = { + .name = "minictrl", + .init = quickpanel_minictrl_init, + .fini = quickpanel_minictrl_fini, + .suspend = NULL, + .resume = NULL, + .hib_enter = NULL, + .hib_leave = NULL, + .lang_changed = NULL, + .refresh = NULL, + .get_height = quickpanel_minictrl_get_height, +}; + +struct _viewer_item { + char *name; + unsigned int width; + unsigned int height; + minicontrol_priority_e priority; + Evas_Object *viewer; + Elm_Object_Item *it; + void *data; +}; + +GHashTable *g_prov_table; + +static void _viewer_set_size(Evas_Object *viewer, void *data, int width, int height) +{ + retif(viewer == NULL, , "Invalid parameter!"); + retif(data == NULL, , "Invalid parameter!"); + retif(width < 0, , "Invalid parameter!"); + retif(height < 0, , "Invalid parameter!"); + struct appdata *ad = data; + int max_width = 0; + int resized_width = 0; + + DBG("mini w:%d h:%d", width, height); + + if (ad->angle == 90 || ad->angle == 270) { + max_width = (ad->scale * MINICONTROL_WIDTH_L_MAX) - 1; + } else { + max_width = (ad->scale * MINICONTROL_WIDTH_P_MAX) - 1; + } + resized_width = (width > max_width) ? max_width : width; + evas_object_size_hint_min_set(viewer, resized_width, height); +} + +static void _viewer_item_free(struct _viewer_item *item) +{ + if (!item) + return; + + if (item->name) + free(item->name); + + if (item->it) + elm_object_item_del(item->it); + + if (item->viewer) { + evas_object_unref(item->viewer); + evas_object_del(item->viewer); + } + + free(item); +} + +#if 0 +static Evas_Object *_minictrl_load_viewer(Evas_Object *parent, + struct _viewer_item *item) +{ + Evas_Object *viewer = NULL; + + if (!parent) { + ERR("parent is NULL"); + return NULL; + } + + if (!item) { + ERR("item is NULL"); + return NULL; + } + + if (!item->name) { + ERR("item name is NULL"); + return NULL; + } + + viewer = minicontrol_viewer_add(parent, item->name); + if (!viewer) { + ERR("fail to create viewer for [%s]", item->name); + return NULL; + } + + evas_object_size_hint_min_set(viewer, item->width - QP_R_MARGIN , item->height); + + return viewer; +} +#endif + +static Evas_Object *_minictrl_gl_get_content(void *data, Evas_Object * obj, + const char *part) +{ + Evas_Object *content = NULL; + qp_item_data *qid = NULL; + struct _viewer_item *item = NULL; + + retif(data == NULL, NULL, "Invalid parameter!"); + qid = data; + + item = quickpanel_list_util_item_get_data(qid); + retif(!item, NULL, "item is NULL"); + + if (strcmp(part, "elm.icon") == 0) + content = item->viewer; + + return content; +} + + +static Eina_Bool _minictrl_gl_get_state(void *data, Evas_Object *obj, + const char *part) +{ + return EINA_FALSE; +} + +static void _minictrl_gl_del(void *data, Evas_Object *obj) +{ + if (data) { + quickpanel_list_util_del_count(data); + free(data); + } + + return; +} + +static Elm_Genlist_Item_Class *_minictrl_gl_style_get(void) +{ + Elm_Genlist_Item_Class *itc = NULL; + + itc = elm_genlist_item_class_new(); + if (!itc) { + ERR("fail to elm_genlist_item_class_new()"); + return NULL; + } + + itc->item_style = "minicontrol/default"; + itc->func.text_get = NULL; + itc->func.content_get = _minictrl_gl_get_content; + itc->func.state_get = _minictrl_gl_get_state; + itc->func.del = _minictrl_gl_del; + + return itc; +} + +static int _minictrl_is_ongoing(const char *str) +{ + if (str == NULL) return 0; + + if (strstr(str, MINICONTROL_TYPE_STR_ONGOING) != NULL) { + return 1; + } else { + return 0; + } +} + +qp_item_type_e _minictrl_priority_to_type(minicontrol_priority_e priority) +{ + qp_item_type_e type; + + switch (priority) { + case MINICONTROL_PRIORITY_TOP: + type = QP_ITEM_TYPE_MINICTRL_TOP; + break; + case MINICONTROL_PRIORITY_MIDDLE: + type = QP_ITEM_TYPE_MINICTRL_MIDDLE; + break; + case MINICONTROL_PRIORITY_LOW: + default: + type = QP_ITEM_TYPE_MINICTRL_LOW; + break; + } + + return type; +} + +static void _minictrl_add(const char *name, unsigned int width, + unsigned int height, + minicontrol_priority_e priority, + void *data) +{ + qp_item_data *qid = NULL; + Elm_Genlist_Item_Class *itc = NULL; + struct _viewer_item *vit = NULL; + qp_item_type_e type; + struct appdata *ad; + Evas_Object *viewer = NULL; + + retif(!name, , "name is NULL"); + retif(!data, , "data is NULL"); + + ad = data; + retif(!ad->list, , "list is NULL"); + + if (g_prov_table) { + struct _viewer_item *found = NULL; + found = g_hash_table_lookup(g_prov_table, name); + + if (found) { + ERR("already have it : %s", name); + return; + } + } else { + ERR("g_prov_table is NULL"); + return; + } + + /* elm_plug receives 'server_del' event, + * if it repeats connect and disconnect frequently. + * + */ + viewer = minicontrol_viewer_add(ad->list, name); + if (!viewer) { + ERR("fail to add viewer - %s", name); + return; + } + evas_object_ref(viewer); + _viewer_set_size(viewer, ad, width, height); + + itc = _minictrl_gl_style_get(); + if (!itc) { + ERR("fail to _minictrl_gl_style_get()"); + evas_object_del(viewer); + return; + } + + vit = malloc(sizeof(struct _viewer_item)); + if (!vit) { + ERR("fail to alloc vit"); + evas_object_del(viewer); + elm_genlist_item_class_free(itc); + return; + } + + + if (_minictrl_is_ongoing(name) == 1) { + DBG("QP_ITEM_TYPE_MINICTRL_ONGOING is added"); + type = QP_ITEM_TYPE_MINICTRL_ONGOING; + } else { + type = _minictrl_priority_to_type(priority); + } + qid = quickpanel_list_util_item_new(type, vit); + if (!qid) { + ERR("fail to alloc vit"); + evas_object_del(viewer); + elm_genlist_item_class_free(itc); + free(vit); + return; + } + vit->name = strdup(name); + vit->width = width; + vit->height = height; + vit->priority = priority; + vit->viewer = viewer; + vit->data = data; + vit->it = quickpanel_list_util_sort_insert(ad->list, itc, qid, NULL, + ELM_GENLIST_ITEM_NONE, NULL, NULL); + + g_hash_table_insert(g_prov_table, g_strdup(name), vit); + + INFO("success to add %s", name); + + elm_genlist_item_class_free(itc); + + quickpanel_ui_update_height(ad); +} + +static void _minictrl_remove(const char *name, void *data) +{ + if (g_prov_table) { + if (g_hash_table_remove(g_prov_table, name)) + { + INFO("success to remove %s", name); + + retif(data == NULL, , "data is NULL"); + quickpanel_ui_update_height(data); + } + else + WARN("unknown provider name : %s", name); + } +} + +static void _minictrl_update(const char *name, unsigned int width, + unsigned int height, void *data) +{ + struct _viewer_item *found = NULL; + struct appdata *ad = NULL; + + if (!g_prov_table) + return; + + retif(!data, , "data is NULL"); + ad = data; + + found = g_hash_table_lookup(g_prov_table, name); + + if (!found) { + WARN("unknown provider name : %s", name); + return; + } + + found->width = width; + found->height = height; + + if (found->viewer) { + _viewer_set_size(found->viewer, ad, width, height); + } + + if (found->it) { + elm_genlist_item_update(found->it); + quickpanel_ui_update_height(ad); + } +} + +static void _minictrl_request(const char *name, int action, void *data) +{ + Ecore_X_Window xwin; + struct appdata *ad = NULL; + retif(!name, , "name is NULL"); + retif(!data, , "data is NULL"); + ad = data; + + if (action == MINICONTROL_REQ_HIDE_VIEWER) { + xwin = elm_win_xwindow_get(ad->win); + if (xwin != 0) { + DBG("close by minictrl:%s", name); + debug_printf("close by minictrl:%s", name); + ecore_x_e_illume_quickpanel_state_send(ecore_x_e_illume_zone_get(xwin),ECORE_X_ILLUME_QUICKPANEL_STATE_OFF); + } + } +} + +static void _mctrl_monitor_cb(minicontrol_action_e action, + const char *name, unsigned int width, + unsigned int height, + minicontrol_priority_e priority, + void *data) +{ + retif(!data, , "data is NULL"); + retif(!name, , "name is NULL"); + + switch (action) { + case MINICONTROL_ACTION_START: + _minictrl_add(name, width, height, priority, data); + break; + case MINICONTROL_ACTION_RESIZE: + _minictrl_update(name, width, height, data); + break; + case MINICONTROL_ACTION_STOP: + _minictrl_remove(name, data); + break; + case MINICONTROL_ACTION_REQUEST: + _minictrl_request(name, width, data); + break; + default: + break; + } +} + +static int quickpanel_minictrl_init(void *data) +{ + minicontrol_error_e ret; + + retif(!data, QP_FAIL, "Invalid parameter!"); + + g_prov_table = g_hash_table_new_full(g_str_hash, g_str_equal, + (GDestroyNotify)g_free, + (GDestroyNotify)_viewer_item_free); + + ret = minicontrol_monitor_start(_mctrl_monitor_cb, data); + if (ret != MINICONTROL_ERROR_NONE) { + ERR("fail to minicontrol_monitor_start()- %d", ret); + return QP_FAIL; + } + + return QP_OK; +} + +static int quickpanel_minictrl_fini(void *data) +{ + minicontrol_error_e ret; + ret = minicontrol_monitor_stop(); + if (ret != MINICONTROL_ERROR_NONE) + ERR("fail to minicontrol_monitor_stop()- %d", ret); + + if (g_prov_table) { + g_hash_table_remove_all(g_prov_table); + g_prov_table = NULL; + } + + return QP_OK; +} + + +static void _quickpanel_minictrl_hf_sum_height(gpointer key, gpointer value, gpointer data) +{ + struct _viewer_item *item = value; + + if (item != NULL && data != NULL) { + *((unsigned int *)data) += item->height; + } +} + +static unsigned int quickpanel_minictrl_get_height(void *data) +{ + unsigned int height_minictrl = 0; + + if (g_prov_table != NULL) { + g_hash_table_foreach(g_prov_table, _quickpanel_minictrl_hf_sum_height, &height_minictrl); + } + + return height_minictrl; +} diff --git a/daemon/modules.c b/daemon/modules.c new file mode 100755 index 0000000..a1ddd81 --- /dev/null +++ b/daemon/modules.c @@ -0,0 +1,197 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 "common.h" +#include "modules.h" + +/******************************************************************* + * + * MODULES + * + *****************************************************************/ +/* searchbar */ +/* extern QP_Module searchbar; */ +#ifdef QP_MINICTRL_ENABLE +extern QP_Module minictrl; +#endif /* QP_MINICTRL_ENABLE */ +#ifdef QP_BRIGHTNESS_ENABLE +/* brightness */ +extern QP_Module brightness_ctrl; +#endif /* QP_BRIGHTNESS_ENABLE */ +/* notification */ +extern QP_Module noti; +extern QP_Module ticker; +extern QP_Module ticker_status; +/* idle test */ +extern QP_Module idletxt; + +static QP_Module *modules[] = { +#ifdef QP_MINICTRL_ENABLE + &minictrl, +#endif /* QP_MINICTRL_ENABLE */ +#ifdef QP_BRIGHTNESS_ENABLE + &brightness_ctrl, +#endif /* QP_BRIGHTNESS_ENABLE */ + ¬i, + &ticker, + &ticker_status, + &idletxt +}; + +int init_modules(void *data) +{ + int i; + + retif(data == NULL, QP_FAIL, "Invalid parameter!"); + + for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) { + if (modules[i]->init) + modules[i]->init(data); + } + + return QP_OK; +} + +int fini_modules(void *data) +{ + int i; + + retif(data == NULL, QP_FAIL, "Invalid parameter!"); + + for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) { + if (modules[i]->fini) + modules[i]->fini(data); + } + + return QP_OK; +} + +int suspend_modules(void *data) +{ + int i; + + retif(data == NULL, QP_FAIL, "Invalid parameter!"); + + for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) { + if (modules[i]->suspend) + modules[i]->suspend(data); + } + + return QP_OK; +} + +int resume_modules(void *data) +{ + int i; + + retif(data == NULL, QP_FAIL, "Invalid parameter!"); + + for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) { + if (modules[i]->resume) + modules[i]->resume(data); + } + + return QP_OK; +} + +int hib_enter_modules(void *data) +{ + int i; + + retif(data == NULL, QP_FAIL, "Invalid parameter!"); + + for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) { + if (modules[i]->hib_enter) + modules[i]->hib_enter(data); + } + + return QP_OK; +} + +int hib_leave_modules(void *data) +{ + int i; + + retif(data == NULL, QP_FAIL, "Invalid parameter!"); + + for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) { + if (modules[i]->hib_leave) + modules[i]->hib_leave(data); + } + + return QP_OK; +} + +/****************************************************************** + * + * LANGUAGE + * + ****************************************************************/ + +void lang_change_modules(void *data) +{ + int i; + retif(data == NULL, , "Invalid parameter!"); + + for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) { + if (modules[i]->lang_changed) + modules[i]->lang_changed(data); + } +} + +void refresh_modules(void *data) +{ + int i; + retif(data == NULL, , "Invalid parameter!"); + + for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) { + if (modules[i]->refresh) + modules[i]->refresh(data); + } +} + +/****************************************************************** + * + * Quickpanel open/close Events + * + ****************************************************************/ +int qp_opened_modules(void *data) +{ + int i; + + retif(data == NULL, QP_FAIL, "Invalid parameter!"); + + for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) { + if (modules[i]->qp_opened) + modules[i]->qp_opened(data); + } + + return QP_OK; +} + +int qp_closed_modules(void *data) +{ + int i; + + retif(data == NULL, QP_FAIL, "Invalid parameter!"); + + for (i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) { + if (modules[i]->qp_closed) + modules[i]->qp_closed(data); + } + + return QP_OK; +} diff --git a/daemon/modules.h b/daemon/modules.h new file mode 100755 index 0000000..99ec615 --- /dev/null +++ b/daemon/modules.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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. + */ + +#ifndef __QP_MODULES_H__ +#define __QP_MODULES_H__ + +#include <stdlib.h> +#include "quickpanel-ui.h" + +extern int init_modules(void *data); +extern int fini_modules(void *data); +extern int suspend_modules(void *data); +extern int resume_modules(void *data); +extern int hib_enter_modules(void *data); +extern int hib_leave_modules(void *data); +extern void lang_change_modules(void *data); +extern void refresh_modules(void *data); +extern int qp_opened_modules(void *data); +extern int qp_closed_modules(void *data); + +#endif /* __QP_MODULES_H__ */ diff --git a/daemon/notifications/brightness.c b/daemon/notifications/brightness.c new file mode 100755 index 0000000..1a98da7 --- /dev/null +++ b/daemon/notifications/brightness.c @@ -0,0 +1,464 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <glib.h> +#include <string.h> +#include <vconf.h> +#include <device.h> +#include "common.h" +#include "quickpanel-ui.h" +#include "list_util.h" +#include "quickpanel_theme_def.h" + +#define BRIGHTNESS_MIN 1 +#define BRIGHTNESS_MAX 100 + +#define QP_BRIGHTNESS_CONTROL_ICON_IMG ICONDIR"/Q02_Notification_brightness.png" + +static int quickpanel_brightness_init(void *data); +static int quickpanel_brightness_fini(void *data); +static void quickpanel_brightness_lang_changed(void *data); +static unsigned int quickpanel_brightness_get_height(void *data); +static void quickpanel_brightness_qp_opened(void *data); +static void quickpanel_brightness_qp_closed(void *data); + +QP_Module brightness_ctrl = { + .name = "brightness_ctrl", + .init = quickpanel_brightness_init, + .fini = quickpanel_brightness_fini, + .suspend = NULL, + .resume = NULL, + .hib_enter = NULL, + .hib_leave = NULL, + .lang_changed = quickpanel_brightness_lang_changed, + .refresh = NULL, + .get_height = quickpanel_brightness_get_height, + .qp_opened = quickpanel_brightness_qp_opened, + .qp_closed = quickpanel_brightness_qp_closed, +}; + +typedef struct _brightness_ctrl_obj { + int min_level; + int max_level; + Evas_Object *checker; + Evas_Object *slider; + Elm_Object_Item *it; + void *data; +} brightness_ctrl_obj; + +brightness_ctrl_obj *g_ctrl_obj; + +static void _brightness_vconf_cb(keynode_t *key, void* data) { + brightness_ctrl_obj *ctrl_obj = NULL; + + retif(data == NULL, , "Data parameter is NULL"); + ctrl_obj = data; + + if (ctrl_obj->it != NULL) { + elm_genlist_item_fields_update(ctrl_obj->it, "elm.check.swallow", ELM_GENLIST_ITEM_FIELD_CONTENT); + elm_genlist_item_fields_update(g_ctrl_obj->it, "elm.swallow.slider", ELM_GENLIST_ITEM_FIELD_CONTENT); + } +} + +static void quickpanel_brightness_qp_opened(void *data) +{ + struct appdata *ad = NULL; + + retif(data == NULL, , "Invalid parameter!"); + ad = data; + + retif(g_ctrl_obj == NULL, , "Invalid parameter!"); + + if (g_ctrl_obj->it != NULL) { + elm_genlist_item_fields_update(g_ctrl_obj->it, "elm.swallow.slider", ELM_GENLIST_ITEM_FIELD_CONTENT); + elm_genlist_item_fields_update(g_ctrl_obj->it, "elm.check.swallow", ELM_GENLIST_ITEM_FIELD_CONTENT); + vconf_ignore_key_changed(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, _brightness_vconf_cb); + } +} + +static void quickpanel_brightness_qp_closed(void *data) +{ + struct appdata *ad = NULL; + + retif(data == NULL, , "Invalid parameter!"); + ad = data; + + retif(g_ctrl_obj == NULL, , "Invalid parameter!"); + + if (g_ctrl_obj->it != NULL) { + vconf_notify_key_changed(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, _brightness_vconf_cb, g_ctrl_obj); + } +} + +int _brightness_is_low_battery(void) { + int battery_value; + + vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &battery_value); + + if (battery_value < VCONFKEY_SYSMAN_BAT_WARNING_LOW) + return 1; + else + return 0; +} + +int _brightness_set_level(int level) { + int ret = DEVICE_ERROR_NONE; + + ret = device_set_brightness_to_settings(0, level); + if (ret != DEVICE_ERROR_NONE) { + ERR("failed to set brightness"); + } + + return level; +} + +int _brightness_get_level(void) { + int level = 0; + + if (vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, &level) == 0) + return level; + else + return SETTING_BRIGHTNESS_LEVEL5; +} + +int _brightness_set_automate_level(int is_on) { + return vconf_set_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, is_on); +} + +int _brightness_get_automate_level(void) { + int is_on = 0; + + if (vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &is_on) == 0) + return is_on; + else + return SETTING_BRIGHTNESS_AUTOMATIC_OFF; +} + +static void +_brightness_ctrl_slider_changed_cb(void *data, + Evas_Object *obj, + void *event_info) +{ + int ret = DEVICE_ERROR_NONE; + int value = 0; + static int old_val = -1; + brightness_ctrl_obj *ctrl_obj = NULL; + + DBG(""); + + retif(data == NULL, , "Data parameter is NULL"); + ctrl_obj = data; + + if (ctrl_obj->checker != NULL) { + value = elm_check_state_get(ctrl_obj->checker); + if (value == 1) { /* it is automatic setting mode, */ + /* do nothing */ + return; + } + } + + double val = elm_slider_value_get(obj); + value = (int)(val + 0.5); + + DBG("value:%d old_val:%d", value, old_val); + + if (value != old_val) + { + DBG("min_level:%d max_level:%d", ctrl_obj->min_level, ctrl_obj->max_level); + if (value >= ctrl_obj->min_level && value <= ctrl_obj->max_level) { + DBG("new brgt:%d", value); + ret = device_set_brightness_to_settings(0, value); + old_val = value; + if (ret != DEVICE_ERROR_NONE) { + ERR("failed to set brightness"); + } + } + } +} + +static void +_brightness_ctrl_slider_delayed_changed_cb(void *data, + Evas_Object *obj, + void *event_info) +{ + int ret = DEVICE_ERROR_NONE; + int value = 0; + + ret = device_get_brightness(0, &value); + + DBG("ret:%d value:%d", ret, value); + if (ret == DEVICE_ERROR_NONE) { + DBG("delayed new brgt:%d", value); + _brightness_set_level(value); + } +} + +static void _brightness_ctrl_checker_toggle_cb(void *data, + Evas_Object * obj, + void *event_info) +{ + retif(obj == NULL, , "obj parameter is NULL"); + + int status = elm_check_state_get(obj); + brightness_ctrl_obj *ctrl_obj = NULL; + + retif(data == NULL, , "Data parameter is NULL"); + ctrl_obj = data; + + _brightness_set_automate_level(status); + + if (ctrl_obj->it != NULL) { + elm_genlist_item_fields_update(ctrl_obj->it, "elm.swallow.slider", ELM_GENLIST_ITEM_FIELD_CONTENT); + elm_genlist_item_fields_update(ctrl_obj->it, "elm.check.swallow", ELM_GENLIST_ITEM_FIELD_CONTENT); + } +} + +static char *_quickpanel_noti_gl_get_text(void *data, Evas_Object * obj, + const char *part) +{ + if (strcmp(part, "elm.check.text") == 0) { + return strdup(_("IDS_QP_BODY_AUTO")); + } + if (strcmp(part, "elm.text.label") == 0) { + return strdup(_S("IDS_COM_OPT_BRIGHTNESS")); + } + return NULL; +} + +static Evas_Object *_brightness_gl_get_content(void *data, Evas_Object * obj, + const char *part) +{ + qp_item_data *qid = NULL; + brightness_ctrl_obj *ctrl_obj = NULL; + + retif(data == NULL, NULL, "Invalid parameter!"); + qid = data; + + ctrl_obj = quickpanel_list_util_item_get_data(qid); + retif(!ctrl_obj, NULL, "item is NULL"); + + if (strcmp(part, "elm.swallow.thumbnail") == 0) { + Evas_Object *image = elm_image_add(obj); + + if (image != NULL) { + elm_image_file_set(image, QP_BRIGHTNESS_CONTROL_ICON_IMG, NULL); + elm_image_resizable_set(image, EINA_FALSE, EINA_TRUE); + } + + return image; + } else if (strcmp(part, "elm.swallow.slider") == 0) { + int value = _brightness_get_level(); + Evas_Object *slider = elm_slider_add(obj); + + if (slider != NULL) { + ctrl_obj->slider = NULL; + elm_object_style_set(slider, "quickpanel"); + elm_slider_indicator_format_set(slider, "%1.0f"); + + evas_object_size_hint_weight_set(slider, EVAS_HINT_EXPAND, 0.0); + evas_object_size_hint_align_set(slider, EVAS_HINT_FILL, 0.5); + elm_slider_min_max_set(slider, ctrl_obj->min_level, ctrl_obj->max_level); + elm_slider_value_set(slider, value); + evas_object_smart_callback_add(slider, "changed", _brightness_ctrl_slider_changed_cb, ctrl_obj); + evas_object_smart_callback_add(slider, "delay,changed", _brightness_ctrl_slider_delayed_changed_cb, ctrl_obj); + + if (_brightness_get_automate_level() || _brightness_is_low_battery() == 1) { + elm_object_disabled_set(slider, EINA_TRUE); + } else { + elm_object_disabled_set(slider, EINA_FALSE); + } + + ctrl_obj->slider = slider; + return slider; + } + } else if (strcmp(part, "elm.check.swallow") == 0) { + Evas_Object *checker = elm_check_add(obj); + + if (checker != NULL) { + ctrl_obj->checker = NULL; + + elm_object_style_set(checker, "quickpanel"); + elm_check_state_set(checker, _brightness_get_automate_level()); + evas_object_smart_callback_add(checker,"changed",_brightness_ctrl_checker_toggle_cb , ctrl_obj); + + if (_brightness_is_low_battery() == 1) { + elm_object_disabled_set(checker, EINA_TRUE); + } else { + elm_object_disabled_set(checker, EINA_FALSE); + } + ctrl_obj->checker = checker; + + return checker; + } + } + + return NULL; +} + +static Eina_Bool _brightness_gl_get_state(void *data, Evas_Object *obj, + const char *part) +{ + return EINA_FALSE; +} + +static void _brightness_gl_del(void *data, Evas_Object *obj) +{ + if (data) { + quickpanel_list_util_del_count(data); + free(data); + } + + return; +} + +static Elm_Genlist_Item_Class *_brightness_gl_style_get(void) +{ + Elm_Genlist_Item_Class *itc = NULL; + + itc = elm_genlist_item_class_new(); + if (!itc) { + ERR("fail to elm_genlist_item_class_new()"); + return NULL; + } + + itc->item_style = "brightness_controller/default"; + itc->func.text_get = _quickpanel_noti_gl_get_text; + itc->func.content_get = _brightness_gl_get_content; + itc->func.state_get = _brightness_gl_get_state; + itc->func.del = _brightness_gl_del; + + return itc; +} + +static void _brightness_add(brightness_ctrl_obj *ctrl_obj, void *data) +{ + qp_item_data *qid = NULL; + Elm_Genlist_Item_Class *itc = NULL; + qp_item_type_e type = QP_ITEM_TYPE_BRIGHTNESS; + struct appdata *ad; + + ad = data; + retif(!ad->list, , "list is NULL"); + + itc = _brightness_gl_style_get(); + if (!itc) { + ERR("fail to _brightness_gl_style_get()"); + return; + } + + qid = quickpanel_list_util_item_new(type, ctrl_obj); + if (!qid) { + ERR("fail to alloc vit"); + elm_genlist_item_class_free(itc); + free(g_ctrl_obj); + return; + } + ctrl_obj->data = data; + ctrl_obj->it = quickpanel_list_util_sort_insert(ad->list, itc, qid, NULL, + ELM_GENLIST_ITEM_NONE, NULL, NULL); + + elm_genlist_item_class_free(itc); + + quickpanel_ui_update_height(ad); +} + +static void _brightness_remove(brightness_ctrl_obj *ctrl_obj, void *data) +{ + if (g_ctrl_obj != NULL) { + INFO("success to remove brightness controller"); + free(g_ctrl_obj); + g_ctrl_obj = NULL; + retif(data == NULL, , "data is NULL"); + quickpanel_ui_update_height(data); + } +} + +static void _brightness_register_event_cb(brightness_ctrl_obj *ctrl_obj) +{ + retif(ctrl_obj == NULL, , "Invalid parameter!"); + + vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, _brightness_vconf_cb, ctrl_obj); + vconf_notify_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, _brightness_vconf_cb, ctrl_obj); +} + +static void _brightness_deregister_event_cb(brightness_ctrl_obj *ctrl_obj) +{ + retif(ctrl_obj == NULL, , "Invalid parameter!"); + + vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, _brightness_vconf_cb); + vconf_ignore_key_changed(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, _brightness_vconf_cb); +} + +static int quickpanel_brightness_init(void *data) +{ + retif(data == NULL, QP_FAIL, "Invalid parameter!"); + + if (g_ctrl_obj == NULL) { + DBG("brightness controller alloced"); + g_ctrl_obj = (brightness_ctrl_obj *)malloc(sizeof(brightness_ctrl_obj)); + } + + DBG(""); + + if (g_ctrl_obj != NULL) { + g_ctrl_obj->min_level = BRIGHTNESS_MIN; + g_ctrl_obj->max_level = BRIGHTNESS_MAX; + + DBG("brightness range %d~%d\n", g_ctrl_obj->min_level, g_ctrl_obj->max_level); + + _brightness_add(g_ctrl_obj, data); + _brightness_register_event_cb(g_ctrl_obj); + } + + return QP_OK; +} + +static int quickpanel_brightness_fini(void *data) +{ + retif(data == NULL, QP_FAIL, "Invalid parameter!"); + + if (g_ctrl_obj != NULL) { + _brightness_deregister_event_cb(g_ctrl_obj); + _brightness_remove(g_ctrl_obj, data); + } + + _brightness_remove(g_ctrl_obj, data); + + g_ctrl_obj = NULL; + return QP_OK; +} + +static void quickpanel_brightness_lang_changed(void *data) +{ + retif(data == NULL, , "Invalid parameter!"); + + if (g_ctrl_obj != NULL && g_ctrl_obj->it != NULL) { + elm_genlist_item_fields_update(g_ctrl_obj->it, "elm.check.text", ELM_GENLIST_ITEM_FIELD_TEXT); + elm_genlist_item_fields_update(g_ctrl_obj->it, "elm.text.label", ELM_GENLIST_ITEM_FIELD_TEXT); + } +} + +static unsigned int quickpanel_brightness_get_height(void *data) +{ + struct appdata *ad = data; + + retif(ad == NULL, 0, "Invalid parameter!"); + + if (g_ctrl_obj != NULL) + return QP_THEME_LIST_ITEM_BRIGHTNESS_HEIGHT * ad->scale; + else + return 0; +} diff --git a/daemon/notifications/noti.c b/daemon/notifications/noti.c new file mode 100755 index 0000000..ecec5c3 --- /dev/null +++ b/daemon/notifications/noti.c @@ -0,0 +1,1999 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <appsvc.h> + +#include <time.h> +#include <vconf.h> +#include <appcore-common.h> +#include <app_service.h> +#include <runtime_info.h> +#include <Ecore_X.h> + +#include <unicode/uloc.h> +#include <unicode/udat.h> +#include <unicode/udatpg.h> +#include <unicode/ustring.h> +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE +#include "noti_node.h" +#endif +#include <notification.h> + +#include "quickpanel-ui.h" +#include "common.h" +#include "list_util.h" +#include "quickpanel_theme_def.h" +#include "noti_gridbox.h" +#include "noti_box.h" +#include "noti.h" + +#ifndef VCONFKEY_QUICKPANEL_STARTED +#define VCONFKEY_QUICKPANEL_STARTED "memory/private/"PACKAGE_NAME"/started" +#endif /* VCONFKEY_QUICKPANEL_STARTED */ + +#define QP_DEFAULT_ICON ICONDIR"/quickpanel_icon_default.png" +#define QP_NOTI_DAY_DEC (24 * 60 * 60) + +#define QP_NOTI_ONGOING_DBUS_PATH "/dbus/signal" +#define QP_NOTI_ONGOING_DBUS_INTERFACE "notification.ongoing" + +static int suspended; + +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE +noti_node *g_noti_node; +#else +static notification_list_h g_notification_list; +static notification_list_h g_notification_ongoing_list; +#endif +static Eina_List *g_animated_image_list; + +static Evas_Object *g_noti_gridbox; +static Elm_Genlist_Item_Class *itc_noti; +static Elm_Genlist_Item_Class *itc_ongoing; +static Elm_Genlist_Item_Class *g_itc; + +static Evas_Object *g_window; + +static Elm_Object_Item *noti_group; +static Elm_Object_Item *ongoing_first; +static Elm_Object_Item *noti_first; + +static int quickpanel_noti_init(void *data); +static int quickpanel_noti_fini(void *data); +static int quickpanel_noti_suspend(void *data); +static int quickpanel_noti_resume(void *data); +static void quickpanel_noti_lang_changed(void *data); +static void quickpanel_noti_refresh(void *data); +static unsigned int quickpanel_noti_get_height(void *data); + +QP_Module noti = { + .name = "noti", + .init = quickpanel_noti_init, + .fini = quickpanel_noti_fini, + .suspend = quickpanel_noti_suspend, + .resume = quickpanel_noti_resume, + .lang_changed = quickpanel_noti_lang_changed, + .hib_enter = NULL, + .hib_leave = NULL, + .refresh = quickpanel_noti_refresh, + .get_height = quickpanel_noti_get_height, +}; + +Eina_Bool _quickpanel_noti_update_notibox_idler(void *data) +{ + retif(data == NULL, ECORE_CALLBACK_CANCEL, "data is null"); + + Elm_Object_Item *item = data; + elm_genlist_item_update(item); + + return ECORE_CALLBACK_CANCEL; +} + +static void _quickpanel_noti_update_notibox(void) { + if (noti_group != NULL) { + ecore_idler_add(_quickpanel_noti_update_notibox_idler, noti_group); + } + + if (noti_first != NULL) { + ecore_idler_add(_quickpanel_noti_update_notibox_idler, noti_first); + } +} + +static void _quickpanel_noti_clear_clicked_cb(void *data, Evas_Object * obj, + void *event_info) +{ + notification_error_e noti_err = NOTIFICATION_ERROR_NONE; + + noti_err = notifiation_clear(NOTIFICATION_TYPE_NOTI); + + DBG("Clear Clicked : noti_err(%d)", noti_err); +} + +static char *_quickpanel_noti_get_progress(notification_h noti, char *buf, + int buf_len) +{ + double size = 0.0; + double percentage = 0.0; + + retif(noti == NULL, NULL, "Invalid parameter!"); + + notification_get_size(noti, &size); + notification_get_progress(noti, &percentage); + + if (percentage < 1 && percentage > 0) { + if (snprintf(buf, buf_len, "%d%%", (int)(percentage * 100)) + <= 0) + return NULL; + + return buf; + } else if (size > 0) { + if (size > (1 << 30)) { + if (snprintf(buf, buf_len, "%.1lfGB", + size / 1000000000.0) <= 0) + return NULL; + + return buf; + } else if (size > (1 << 20)) { + if (snprintf(buf, buf_len, "%.1lfMB", + size / 1000000.0) <= 0) + return NULL; + + return buf; + } else if (size > (1 << 10)) { + if (snprintf(buf, buf_len, "%.1lfKB", + size / 1000.0) <= 0) + return NULL; + + return buf; + } else { + if (snprintf(buf, buf_len, "%lfB", size) <= 0) + return NULL; + + return buf; + } + } + + return NULL; +} + +static notification_h _quickpanel_noti_update_item_progress(const char *pkgname, + int priv_id, + double progress) +{ +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + char *noti_pkgname = NULL; + int noti_priv_id = 0; + + noti_node_item *node = noti_node_get(g_noti_node, priv_id); + + if (node != NULL && node->noti != NULL) { + notification_get_pkgname(node->noti, ¬i_pkgname); + notification_get_id(node->noti, NULL, ¬i_priv_id); + if (!strcmp(noti_pkgname, pkgname) + && priv_id == noti_priv_id) { + notification_set_progress(node->noti, progress); + return node->noti; + } + } +#else + notification_h noti = NULL; + notification_list_h head = NULL; + char *noti_pkgname = NULL; + int noti_priv_id = 0; + + if (g_notification_ongoing_list) { + head = notification_list_get_head(g_notification_ongoing_list); + + while (head != NULL) { + noti = notification_list_get_data(head); + notification_get_pkgname(noti, ¬i_pkgname); + notification_get_id(noti, NULL, ¬i_priv_id); + if (!strcmp(noti_pkgname, pkgname) + && priv_id == noti_priv_id) { + notification_set_progress(noti, progress); + return noti; + } + head = notification_list_get_next(head); + } + } + + if (g_notification_list) { + head = notification_list_get_head(g_notification_list); + + while (head != NULL) { + noti = notification_list_get_data(head); + notification_get_pkgname(noti, ¬i_pkgname); + notification_get_id(noti, NULL, ¬i_priv_id); + if (!strcmp(noti_pkgname, pkgname) + && priv_id == noti_priv_id) { + notification_set_progress(noti, progress); + return noti; + } + head = notification_list_get_next(head); + } + } +#endif + + return NULL; +} + +static notification_h _quickpanel_noti_update_item_size(const char *pkgname, + int priv_id, + double size) +{ +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + char *noti_pkgname = NULL; + int noti_priv_id = 0; + + noti_node_item *node = noti_node_get(g_noti_node, priv_id); + + if (node != NULL && node->noti != NULL) { + notification_get_pkgname(node->noti, ¬i_pkgname); + notification_get_id(node->noti, NULL, ¬i_priv_id); + if (!strcmp(noti_pkgname, pkgname) + && priv_id == noti_priv_id) { + notification_set_size(node->noti, size); + return node->noti; + } + } +#else + notification_h noti = NULL; + notification_list_h head = NULL; + char *noti_pkgname = NULL; + int noti_priv_id = 0; + + if (g_notification_ongoing_list) { + head = notification_list_get_head(g_notification_ongoing_list); + + while (head != NULL) { + noti = notification_list_get_data(head); + notification_get_pkgname(noti, ¬i_pkgname); + notification_get_id(noti, NULL, ¬i_priv_id); + if (!strcmp(noti_pkgname, pkgname) + && priv_id == noti_priv_id) { + notification_set_size(noti, size); + return noti; + } + head = notification_list_get_next(head); + } + } + + if (g_notification_list) { + head = notification_list_get_head(g_notification_list); + + while (head != NULL) { + noti = notification_list_get_data(head); + notification_get_pkgname(noti, ¬i_pkgname); + notification_get_id(noti, NULL, ¬i_priv_id); + if (!strcmp(noti_pkgname, pkgname) + && priv_id == noti_priv_id) { + notification_set_size(noti, size); + return noti; + } + head = notification_list_get_next(head); + } + } +#endif + + return NULL; +} + +static notification_h _quickpanel_noti_update_item_content(const char *pkgname, + int priv_id, + char *content) +{ +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + char *noti_pkgname = NULL; + int noti_priv_id = 0; + + noti_node_item *node = noti_node_get(g_noti_node, priv_id); + + if (node != NULL && node->noti != NULL) { + notification_get_pkgname(node->noti, ¬i_pkgname); + notification_get_id(node->noti, NULL, ¬i_priv_id); + if (!strcmp(noti_pkgname, pkgname) + && priv_id == noti_priv_id) { + notification_set_text(node->noti, + NOTIFICATION_TEXT_TYPE_CONTENT, + content, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); + return node->noti; + } + } +#else + notification_h noti = NULL; + notification_list_h head = NULL; + char *noti_pkgname = NULL; + int noti_priv_id = 0; + + if (g_notification_ongoing_list) { + head = notification_list_get_head(g_notification_ongoing_list); + + while (head != NULL) { + noti = notification_list_get_data(head); + notification_get_pkgname(noti, ¬i_pkgname); + notification_get_id(noti, NULL, ¬i_priv_id); + if (!strcmp(noti_pkgname, pkgname) + && priv_id == noti_priv_id) { + notification_set_text(noti, + NOTIFICATION_TEXT_TYPE_CONTENT, + content, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); + return noti; + } + head = notification_list_get_next(head); + } + } + + if (g_notification_list) { + head = notification_list_get_head(g_notification_list); + + while (head != NULL) { + noti = notification_list_get_data(head); + notification_get_pkgname(noti, ¬i_pkgname); + notification_get_id(noti, NULL, ¬i_priv_id); + if (!strcmp(noti_pkgname, pkgname) + && priv_id == noti_priv_id) { + notification_set_text(noti, + NOTIFICATION_TEXT_TYPE_CONTENT, + content, NULL, + NOTIFICATION_VARIABLE_TYPE_NONE); + return noti; + } + head = notification_list_get_next(head); + } + } +#endif + + return NULL; +} + +static void _quickpanel_noti_update_progressbar(void *data, + notification_h update_noti) +{ + struct appdata *ad = NULL; + Elm_Object_Item *found = NULL; + + retif(!data, , "data is NULL"); + ad = data; + + retif(!ad->list, , "ad->list is NULL"); + +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + int priv_id = 0; + + if (notification_get_id(update_noti, NULL, &priv_id) == NOTIFICATION_ERROR_NONE) { + noti_node_item *node = noti_node_get(g_noti_node, priv_id); + + if (node != NULL) { + found = node->view; + } + } +#else + if (ad->show_setting) + found = quickpanel_list_util_find_item_by_type(ad->list, + update_noti, ongoing_first, + QP_ITEM_TYPE_ONGOING_NOTI); + else + found = quickpanel_list_util_find_item_by_type(ad->list, + update_noti, noti_first, + QP_ITEM_TYPE_NOTI); +#endif + + retif(!found, , "fail to find %p related gl item", update_noti); + + elm_genlist_item_fields_update(found, "*", ELM_GENLIST_ITEM_FIELD_ALL); +} + +static void _quickpanel_noti_item_progress_update_cb(void *data, + DBusMessage *msg) +{ + DBusError err; + char *pkgname = 0; + int priv_id = 0; + double progress = 0; + notification_h noti = NULL; + + retif(data == NULL || msg == NULL, , "Invalid parameter!"); + + dbus_error_init(&err); + dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &pkgname, + DBUS_TYPE_INT32, &priv_id, + DBUS_TYPE_DOUBLE, &progress, + DBUS_TYPE_INVALID); + + if (dbus_error_is_set(&err)) { + ERR("dbus err: %s", err.message); + dbus_error_free(&err); + return; + } + + if (pkgname == NULL) { + ERR("pkgname is null"); + return; + } + + /* check item on the list */ + noti = _quickpanel_noti_update_item_progress(pkgname, + priv_id, progress); + retif(noti == NULL, , "Can not found noti data."); + + DBG("pkgname[%s], priv_id[%d], progress[%lf]", + pkgname, priv_id, progress); + if (!suspended) + _quickpanel_noti_update_progressbar(data, noti); +} + +static void _quickpanel_noti_item_size_update_cb(void *data, DBusMessage * msg) +{ + DBusError err; + char *pkgname = 0; + int priv_id = 0; + double size = 0; + notification_h noti = NULL; + + retif(data == NULL || msg == NULL, , "Invalid parameter!"); + + dbus_error_init(&err); + dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &pkgname, + DBUS_TYPE_INT32, &priv_id, + DBUS_TYPE_DOUBLE, &size, DBUS_TYPE_INVALID); + if (dbus_error_is_set(&err)) { + ERR("dbus err: %s", err.message); + dbus_error_free(&err); + return; + } + + if (pkgname == NULL) { + ERR("pkgname is null"); + return; + } + + /* check item on the list */ + noti = _quickpanel_noti_update_item_size(pkgname, priv_id, size); + retif(noti == NULL, , "Can not found noti data."); + + DBG("pkgname[%s], priv_id[%d], progress[%lf]", + pkgname, priv_id, size); + + if (!suspended) + _quickpanel_noti_update_progressbar(data, noti); +} + +static void _quickpanel_noti_item_content_update_cb(void *data, + DBusMessage *msg) +{ + DBusError err; + char *pkgname = NULL; + int priv_id = 0; + char *content = NULL; + notification_h noti = NULL; + + retif(data == NULL || msg == NULL, , "Invalid parameter!"); + + dbus_error_init(&err); + dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &pkgname, + DBUS_TYPE_INT32, &priv_id, + DBUS_TYPE_STRING, &content, DBUS_TYPE_INVALID); + + if (pkgname == NULL) { + ERR("pkgname is null"); + return; + } + if (content == NULL) { + ERR("content is null"); + return; + } + + if (dbus_error_is_set(&err)) { + ERR("dbus err: %s", err.message); + dbus_error_free(&err); + return; + } + + DBG("pkgname[%s], priv_id[%d], content[%s]", + pkgname, priv_id, content); + + /* check item on the list */ + noti = _quickpanel_noti_update_item_content(pkgname, priv_id, content); + retif(noti == NULL, , "Can not found noti data."); + + if (!suspended) + _quickpanel_noti_update_progressbar(data, noti); +} + +char *quickpanel_noti_get_time(time_t t, char *buf, int buf_len) +{ + UErrorCode status = U_ZERO_ERROR; + UDateTimePatternGenerator *generator; + UDateFormat *formatter; + UChar skeleton[40] = { 0 }; + UChar pattern[40] = { 0 }; + UChar formatted[40] = { 0 }; + int32_t patternCapacity, formattedCapacity; + int32_t skeletonLength, patternLength, formattedLength; + UDate date; + const char *locale; + const char customSkeleton[] = UDAT_YEAR_NUM_MONTH_DAY; + char bf1[32] = { 0, }; + bool is_24hour_enabled = FALSE; + + struct tm loc_time; + time_t today, yesterday; + int ret = 0; + + today = time(NULL); + localtime_r(&today, &loc_time); + + loc_time.tm_sec = 0; + loc_time.tm_min = 0; + loc_time.tm_hour = 0; + today = mktime(&loc_time); + + yesterday = today - QP_NOTI_DAY_DEC; + + localtime_r(&t, &loc_time); + + if (t >= yesterday && t < today) { + ret = snprintf(buf, buf_len, _S("IDS_COM_BODY_YESTERDAY")); + } else if (t < yesterday) { + /* set UDate from time_t */ + date = (UDate) t * 1000; + + /* get default locale */ + /* for thread saftey */ + uloc_setDefault(__secure_getenv("LC_TIME"), &status); + locale = uloc_getDefault(); + + /* open datetime pattern generator */ + generator = udatpg_open(locale, &status); + if (generator == NULL) + return NULL; + + /* calculate pattern string capacity */ + patternCapacity = + (int32_t) (sizeof(pattern) / sizeof((pattern)[0])); + + /* ascii to unicode for input skeleton */ + u_uastrcpy(skeleton, customSkeleton); + + /* get skeleton length */ + skeletonLength = strlen(customSkeleton); + + /* get best pattern using skeleton */ + patternLength = + udatpg_getBestPattern(generator, skeleton, skeletonLength, + pattern, patternCapacity, &status); + + /* open datetime formatter using best pattern */ + formatter = + udat_open(UDAT_IGNORE, UDAT_DEFAULT, locale, NULL, -1, + pattern, patternLength, &status); + if (formatter == NULL) { + udatpg_close(generator); + return NULL; + } + + /* calculate formatted string capacity */ + formattedCapacity = + (int32_t) (sizeof(formatted) / sizeof((formatted)[0])); + + /* formatting date using formatter by best pattern */ + formattedLength = + udat_format(formatter, date, formatted, formattedCapacity, + NULL, &status); + + /* unicode to ascii to display */ + u_austrcpy(bf1, formatted); + + /* close datetime pattern generator */ + udatpg_close(generator); + + /* close datetime formatter */ + udat_close(formatter); + + ret = snprintf(buf, buf_len, "%s", bf1); + } else { + ret = runtime_info_get_value_bool( + RUNTIME_INFO_KEY_24HOUR_CLOCK_FORMAT_ENABLED, &is_24hour_enabled); + if (ret == RUNTIME_INFO_ERROR_NONE && is_24hour_enabled == TRUE) { + ret = strftime(buf, buf_len, "%H:%M", &loc_time); + } else { + strftime(bf1, sizeof(bf1), "%l:%M", &loc_time); + + if (loc_time.tm_hour >= 0 && loc_time.tm_hour < 12) + ret = snprintf(buf, buf_len, "%s%s", bf1, "AM"); + else + ret = snprintf(buf, buf_len, "%s%s", bf1, "PM"); + } + + } + + return ret <= 0 ? NULL : buf; +} + +static void _quickpanel_noti_ani_image_control(Eina_Bool on) +{ + const Eina_List *l = NULL; + const Eina_List *ln = NULL; + Evas_Object *entry_obj = NULL; + + retif(g_animated_image_list == NULL, ,""); + + EINA_LIST_FOREACH_SAFE(g_animated_image_list, l, ln, entry_obj) { + if (entry_obj == NULL) continue; + + if (on == EINA_TRUE) { + if (elm_image_animated_play_get(entry_obj) == EINA_FALSE) { + elm_image_animated_play_set(entry_obj, EINA_TRUE); + } + } else { + if (elm_image_animated_play_get(entry_obj) == EINA_TRUE) { + elm_image_animated_play_set(entry_obj, EINA_FALSE); + } + } + } +} + +static void _quickpanel_noti_ani_image_deleted_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + retif(obj == NULL, , "obj is NULL"); + retif(g_animated_image_list == NULL, , "list is empty"); + + g_animated_image_list = eina_list_remove(g_animated_image_list, obj); +} + +static Evas_Object *_quickpanel_noti_box_gl_get_content(void *data, + Evas_Object *obj, const char *part) { + retif(part == NULL, NULL, "invalid parameter"); + + if (strcmp(part, "elm.icon") == 0) { + DBG("returned:%p", g_noti_gridbox); + return g_noti_gridbox; + } + + return NULL; +} + +static Evas_Object *_quickpanel_noti_gl_get_content(void *data, + Evas_Object *obj, const char *part) +{ + qp_item_data *qid = NULL; + notification_h noti = NULL; + Evas_Object *ic = NULL; + char *icon_path = NULL; + char *thumbnail_path = NULL; + char *ret_path = NULL; + double size = 0.0; + double percentage = 0.0; + notification_type_e type = NOTIFICATION_TYPE_NONE; + char group_name[64] = {0,}; + notification_ly_type_e layout = NOTIFICATION_LY_NONE ; + + retif(!data, NULL, "data is NULL"); + qid = data; + + noti = quickpanel_list_util_item_get_data(qid); + retif(noti == NULL, NULL, "noti is NULL"); + + if (!strncmp + (part, "elm.swallow.progress", strlen("elm.swallow.progress"))) { + notification_get_type(noti, &type); + if (type == NOTIFICATION_TYPE_ONGOING) { + notification_get_size(noti, &size); + notification_get_progress(noti, &percentage); + notification_get_layout(noti, &layout); + + if (layout != NOTIFICATION_LY_ONGOING_EVENT) { + if (percentage > 0 && percentage <= 1) { + ic = elm_progressbar_add(obj); + if (ic == NULL) + return NULL; + + elm_object_style_set(ic, "quickpanel/list_progress"); + elm_progressbar_value_set(ic, percentage); + elm_progressbar_horizontal_set(ic, EINA_TRUE); + elm_progressbar_pulse(ic, EINA_FALSE); + } else if (size > 0) { + ic = elm_progressbar_add(obj); + if (ic == NULL) + return NULL; + + elm_object_style_set(ic, "quickpanel/pending_list"); + elm_progressbar_horizontal_set(ic, EINA_TRUE); + elm_progressbar_pulse(ic, EINA_TRUE); + } + } + } + return ic; + } + + ic = elm_image_add(obj); + retif(ic == NULL, NULL, "Failed to create elm icon."); + + notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL, + &thumbnail_path); + notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON, &icon_path); + + snprintf(group_name, sizeof(group_name) - 1, "notification_item_%d", eina_list_count(g_animated_image_list)); + + if (!strncmp + (part, "elm.swallow.thumbnail", strlen("elm.swallow.thumbnail"))) { + if (thumbnail_path == NULL) + ret_path = icon_path; + else + ret_path = thumbnail_path; + + elm_image_resizable_set(ic, EINA_FALSE, EINA_TRUE); + + if (ret_path == NULL + || (elm_image_file_set(ic, ret_path, group_name) == EINA_FALSE)) + elm_image_file_set(ic, QP_DEFAULT_ICON, group_name); + } else if (!strncmp(part, "elm.swallow.icon", + strlen("elm.swallow.icon"))) { + if (thumbnail_path == NULL) + ret_path = NULL; + else + ret_path = icon_path; + + if (ret_path != NULL) + elm_image_file_set(ic, ret_path, group_name); + } + + if (ic != NULL && elm_image_animated_available_get(ic) == EINA_TRUE) { + elm_image_animated_set(ic, EINA_TRUE); + g_animated_image_list = eina_list_append(g_animated_image_list, ic); + evas_object_event_callback_add(ic, EVAS_CALLBACK_DEL, _quickpanel_noti_ani_image_deleted_cb, ic); + + if (suspended == 0) + elm_image_animated_play_set(ic, EINA_TRUE); + } + return ic; +} + +static char *_quickpanel_ongoing_noti_gl_get_text(void *data, Evas_Object * obj, + const char *part) +{ + qp_item_data *qid = NULL; + notification_h noti = NULL; + notification_error_e noti_err = NOTIFICATION_ERROR_NONE; + char *text = NULL; + char *domain = NULL; + char *dir = NULL; + char *pkgname = NULL; + char *caller_pkgname = NULL; + int group_id = 0, priv_id = 0; + char buf[128] = { 0, }; + notification_type_e type = NOTIFICATION_TYPE_NONE; + double size = 0.0; + double percentage = 0.0; + int isProgressBarEnabled = 1; + notification_ly_type_e layout = NOTIFICATION_LY_NONE ; + + retif(!data, NULL, "data is NULL"); + qid = data; + + noti = quickpanel_list_util_item_get_data(qid); + retif(noti == NULL, NULL, "noti is NULL"); + + /* Set text domain */ + notification_get_text_domain(noti, &domain, &dir); + if (domain != NULL && dir != NULL) + bindtextdomain(domain, dir); + + /* Get pkgname & id */ + notification_get_pkgname(noti, &pkgname); + notification_get_application(noti, &caller_pkgname); + notification_get_id(noti, &group_id, &priv_id); + notification_get_type(noti, &type); + notification_get_size(noti, &size); + notification_get_progress(noti, &percentage); + notification_get_layout(noti, &layout); + + DBG("percentage:%f size:%f", percentage, size); + + if (percentage <= 0.0 && size <= 0.0) { + isProgressBarEnabled = 0; + } + + if (!strcmp(part, "elm.text.title")) { + noti_err = notification_get_text(noti, + NOTIFICATION_TEXT_TYPE_TITLE, + &text); + if (noti_err != NOTIFICATION_ERROR_NONE) + text = NULL; + } else if (!strcmp(part, "elm.text.content")) { + noti_err = notification_get_text(noti, + NOTIFICATION_TEXT_TYPE_CONTENT, + &text); + if (noti_err != NOTIFICATION_ERROR_NONE) + text = NULL; + } else if (!strcmp(part, "elm.text.time")) { + if (isProgressBarEnabled == 0) + return NULL; + + if (layout == NOTIFICATION_LY_ONGOING_EVENT) { + return NULL; + } + + text = _quickpanel_noti_get_progress(noti, buf, + sizeof(buf)); + } + + if (text != NULL) + return strdup(text); + + return NULL; +} + +static Eina_Bool _quickpanel_noti_gl_get_state(void *data, Evas_Object * obj, + const char *part) +{ + qp_item_data *qid = NULL; + notification_h noti = NULL; + char *pkgname = NULL; + int group_id = 0, priv_id = 0; + char *content = NULL; + time_t time; + + retif(!data, EINA_FALSE, "data is NULL"); + qid = data; + + noti = quickpanel_list_util_item_get_data(qid); + retif(noti == NULL, EINA_FALSE, "noti is NULL"); + + notification_get_pkgname(noti, &pkgname); + notification_get_id(noti, &group_id, &priv_id); + + if (!strcmp(part, "elm.text.content")) { + notification_get_text(noti, + NOTIFICATION_TEXT_TYPE_CONTENT, &content); + if (content != NULL) + return EINA_TRUE; + } else if (!strcmp(part, "elm.text.time")) { + notification_get_time(noti, &time); + + if ((int) time > 0) + return EINA_TRUE; + } + + return EINA_FALSE; +} + +static void _quickpanel_do_noti_delete(notification_h noti) { + char *pkgname = NULL; + char *caller_pkgname = NULL; + int flags = 0, priv_id = 0, flag_delete = 0; + notification_type_e type = NOTIFICATION_TYPE_NONE; + + retif(noti == NULL, , "Invalid parameter!"); + + notification_get_pkgname(noti, &caller_pkgname); + notification_get_application(noti, &pkgname); + if (pkgname == NULL) + pkgname = caller_pkgname; + + notification_get_id(noti, NULL, &priv_id); + notification_get_property(noti, &flags); + notification_get_type(noti, &type); + + if (flags & NOTIFICATION_PROP_PERMANENT_DISPLAY) + flag_delete = 0; + else + flag_delete = 1; + + if (flag_delete == 1 && type == NOTIFICATION_TYPE_NOTI) { + notification_delete_by_priv_id(caller_pkgname, NOTIFICATION_TYPE_NOTI, + priv_id); + } +} + +static void _quickpanel_do_noti_press(notification_h noti) { + char *pkgname = NULL; + char *caller_pkgname = NULL; + bundle *args = NULL; + bundle *group_args = NULL; + bundle *single_service_handle = NULL; + bundle *multi_service_handle = NULL; + int flags = 0, group_id = 0, priv_id = 0, count = 0, flag_launch = 0, + flag_delete = 0; + notification_type_e type = NOTIFICATION_TYPE_NONE; + + retif(noti == NULL, , "Invalid parameter!"); + + notification_get_pkgname(noti, &caller_pkgname); + notification_get_application(noti, &pkgname); + if (pkgname == NULL) + pkgname = caller_pkgname; + + notification_get_id(noti, &group_id, &priv_id); + notification_get_property(noti, &flags); + notification_get_type(noti, &type); + + if (flags & NOTIFICATION_PROP_DISABLE_APP_LAUNCH) + flag_launch = 0; + else + flag_launch = 1; + + if (flags & NOTIFICATION_PROP_DISABLE_AUTO_DELETE) + flag_delete = 0; + else + flag_delete = 1; + + notification_get_execute_option(noti, + NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, + NULL, &single_service_handle); + notification_get_execute_option(noti, + NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH, + NULL, &multi_service_handle); + + if (flag_launch == 1) { + /* Hide quickpanel */ + Ecore_X_Window zone; + zone = ecore_x_e_illume_zone_get(elm_win_xwindow_get(g_window)); + ecore_x_e_illume_quickpanel_state_send(zone, + ECORE_X_ILLUME_QUICKPANEL_STATE_OFF); + + if (group_id != NOTIFICATION_GROUP_ID_NONE) + notification_get_count(type, + caller_pkgname, group_id, + priv_id, &count); + else + count = 1; + + if (count > 1 && multi_service_handle != NULL) + appsvc_run_service(multi_service_handle, 0, NULL, NULL); + else if (single_service_handle != NULL) + appsvc_run_service(single_service_handle, 0, NULL, + NULL); + else { + notification_get_args(noti, &args, &group_args); + + if (count > 1 && group_args != NULL) { + quickpanel_launch_app(pkgname, group_args); + } else { + quickpanel_launch_app(pkgname, args); + } + } + } + +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + if (flag_delete == 1 && type == NOTIFICATION_TYPE_NOTI) { + notification_delete_by_priv_id(caller_pkgname, + NOTIFICATION_TYPE_NOTI, + priv_id); + } +#else + if (flag_delete == 1 && type == NOTIFICATION_TYPE_NOTI) + notification_delete_group_by_priv_id(caller_pkgname, + NOTIFICATION_TYPE_NOTI, priv_id); +#endif +} + +static void quickpanel_notibox_delete_cb(void *data, Evas_Object * obj) { + DBG(""); + noti_node_item *item = data; + retif(item == NULL, , "Invalid parameter!"); + + notification_h noti = item->noti; + retif(noti == NULL, , "Invalid parameter!"); + + _quickpanel_do_noti_delete(noti); + +} + +static void quickpanel_notibox_select_cb(void *data, Evas_Object * obj) { + DBG(""); + noti_node_item *item = data; + retif(item == NULL, , "Invalid parameter!"); + + notification_h noti = item->noti; + retif(noti == NULL, , "Invalid parameter!"); + + _quickpanel_do_noti_press(noti); +} + +static void quickpanel_noti_select_cb(void *data, Evas_Object * obj, + void *event_info) { +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + notification_h noti = (notification_h) quickpanel_list_util_item_get_data(data); +#else + notification_h noti = (notification_h) data; +#endif + + retif(noti == NULL, , "Invalid parameter!"); + + elm_genlist_item_selected_set((Elm_Object_Item *) event_info, EINA_FALSE); + + _quickpanel_do_noti_press(noti); +} + +static Evas_Object *_quickpanel_noti_gl_get_group_content(void *data, + Evas_Object *obj, + const char *part) +{ + Evas_Object *eo = NULL; + + eo = elm_button_add(obj); + retif(eo == NULL, NULL, "Failed to create clear button!"); + + elm_object_style_set(eo, "quickpanel_standard"); + + elm_object_text_set(eo, _S("IDS_COM_BODY_CLEAR_ALL")); + evas_object_smart_callback_add(eo, "clicked", + _quickpanel_noti_clear_clicked_cb, NULL); + + return eo; +} + +static char *_quickpanel_noti_gl_get_group_text(void *data, Evas_Object * obj, + const char *part) +{ + char buf[128] = { 0, }; + int noti_count = 0; + + if (!strncmp(part, "elm.text", 8)) { + char format[256] = { 0, }; + memset(buf, 0x00, sizeof(buf)); + + if (g_noti_node != NULL) { + noti_count = + noti_node_get_item_count(g_noti_node, NOTIFICATION_TYPE_NOTI); + } else { + noti_count = 0; + } + + snprintf(format, sizeof(format), "%s %%d", _("IDS_QP_BODY_NOTIFICATIONS_ABB2")); + snprintf(buf, sizeof(buf), format, noti_count); + + return strdup(buf); + } + + return NULL; +} + +static void _quickpanel_list_noti_gl_del(void *data, Evas_Object *obj) +{ + int noti_priv_id = 0; + qp_item_type_e item_type = QP_ITEM_TYPE_NONE; + notification_h noti = NULL; + + if (data) { + noti = quickpanel_list_util_item_get_data(data); + item_type = quickpanel_list_util_item_get_item_type(data); + + DBG("item type:%d", item_type); + if (noti != NULL) { + if (item_type == QP_ITEM_TYPE_ONGOING_NOTI) { + notification_get_id(noti, NULL, ¬i_priv_id); + noti_node_remove(g_noti_node, noti_priv_id); + DBG("noti:%d removed", noti_priv_id); + } + } + free(data); + } + + return; +} + +static void _quickpanel_list_noti_group_gl_del(void *data, Evas_Object *obj) { + if (data != NULL) { + free(data); + } + return; +} + +static void _quickpanel_notibox_gl_del(void *data, Evas_Object *obj) { + if (data != NULL) { + free(data); + } + return; +} + +static void _quickpanel_noti_gl_style_init(void) +{ + Elm_Genlist_Item_Class *noti = NULL; + Elm_Genlist_Item_Class *noti_ongoing = NULL; + Elm_Genlist_Item_Class *group = NULL; + + /* item style for noti items*/ + noti = elm_genlist_item_class_new(); + if (noti) { + noti->item_style = "qp_notibox/default"; + noti->func.text_get = NULL; + noti->func.content_get = _quickpanel_noti_box_gl_get_content; + noti->func.state_get = NULL; + noti->func.del = _quickpanel_notibox_gl_del; + itc_noti = noti; + } + + noti_ongoing = elm_genlist_item_class_new(); + if (noti_ongoing) { + noti_ongoing->item_style = "notification_ongoing_item"; + noti_ongoing->func.text_get = _quickpanel_ongoing_noti_gl_get_text; + noti_ongoing->func.content_get = _quickpanel_noti_gl_get_content; + noti_ongoing->func.state_get = _quickpanel_noti_gl_get_state; + noti_ongoing->func.del = _quickpanel_list_noti_gl_del; + itc_ongoing = noti_ongoing; + } + + /* item style for noti group title */ + group = elm_genlist_item_class_new(); + if (group) { + group->item_style = "qp_group_title"; + group->func.text_get = _quickpanel_noti_gl_get_group_text; + group->func.content_get = _quickpanel_noti_gl_get_group_content; + group->func.del = _quickpanel_list_noti_group_gl_del; + g_itc = group; + } +} + +static void _quickpanel_noti_gl_style_fini(void) +{ + if (itc_noti) { + elm_genlist_item_class_free(itc_noti); + itc_noti = NULL; + } + + if (itc_ongoing) { + elm_genlist_item_class_free(itc_ongoing); + itc_ongoing = NULL; + } + + if (g_itc) { + elm_genlist_item_class_free(g_itc); + g_itc = NULL; + } + + if (g_animated_image_list) { + g_animated_image_list = eina_list_free(g_animated_image_list); + } +} + +static inline void __ongoing_comp_n_copy(notification_h old, notification_h new) +{ + int priv_id = 0; + int new_priv_id = 0; + char *pkgname = NULL; + char *new_pkgname = NULL; + + if (!old) + return; + + if (!new) + return; + + notification_get_id(old, NULL, &priv_id); + notification_get_id(new, NULL, &new_priv_id); + + notification_get_pkgname(old, &pkgname); + notification_get_pkgname(new, &new_pkgname); + + if (!pkgname || !new_pkgname) + return; + + if (!strcmp(pkgname, new_pkgname) && priv_id == new_priv_id) { + double percentage = 0.0; + double size = 0.0; + time_t insert_time = 0; + time_t new_insert_time = 0; + + notification_get_progress(old, &percentage); + notification_get_size(old, &size); + notification_set_progress(new, percentage); + notification_set_size(new, size); + notification_get_insert_time(old, &insert_time); + notification_get_insert_time(new, &new_insert_time); + + if (insert_time == new_insert_time) { + char *content = NULL; + notification_get_text(old, + NOTIFICATION_TEXT_TYPE_CONTENT, &content); + notification_set_text(new, + NOTIFICATION_TEXT_TYPE_CONTENT, content, + NULL, NOTIFICATION_VARIABLE_TYPE_NONE); + } + } +} + +#ifndef QP_DETAILED_NOTI_CHANGE_CB_ENABLE +static void _quickpanel_noti_get_new_divided_list(void) +{ + notification_list_h new_noti_list = NULL; + notification_list_h head = NULL; + notification_list_h new_head = NULL; + notification_h noti = NULL; + notification_h new_noti = NULL; + + /* Get ongoing list */ + notification_get_grouping_list(NOTIFICATION_TYPE_ONGOING, -1, + &new_noti_list); + if (g_notification_ongoing_list != NULL) { + head = notification_list_get_head(g_notification_ongoing_list); + while (head != NULL) { + new_head = notification_list_get_head(new_noti_list); + while (new_head != NULL) { + noti = notification_list_get_data(head); + new_noti = notification_list_get_data(new_head); + + __ongoing_comp_n_copy(noti, new_noti); + + new_head = notification_list_get_next(new_head); + } + head = notification_list_get_next(head); + } + + notification_free_list(g_notification_ongoing_list); + g_notification_ongoing_list = new_noti_list; + } else { + g_notification_ongoing_list = new_noti_list; + } + + /* Get noti list */ + notification_get_grouping_list(NOTIFICATION_TYPE_NOTI, -1, + &new_noti_list); + if (g_notification_list != NULL) { + notification_free_list(g_notification_list); + g_notification_list = new_noti_list; + } + + g_notification_list = new_noti_list; +} + +static void _quickpanel_noti_get_new_list(void) +{ + notification_list_h new_noti_list = NULL; + notification_list_h head = NULL; + notification_list_h new_head = NULL; + notification_h noti = NULL; + notification_h new_noti = NULL; + notification_type_e new_type = NOTIFICATION_TYPE_NONE; + + if (g_notification_ongoing_list != NULL) { + notification_free_list(g_notification_ongoing_list); + g_notification_ongoing_list = new_noti_list; + } + + /* Get all list */ + notification_get_grouping_list(NOTIFICATION_TYPE_NONE, -1, + &new_noti_list); + if (g_notification_list != NULL) { + head = notification_list_get_head(g_notification_list); + while (head != NULL) { + new_head = notification_list_get_head(new_noti_list); + while (new_head != NULL) { + noti = notification_list_get_data(head); + new_noti = notification_list_get_data(new_head); + + notification_get_type(new_noti, &new_type); + + if (new_type == NOTIFICATION_TYPE_ONGOING) + __ongoing_comp_n_copy(noti, new_noti); + + new_head = notification_list_get_next(new_head); + } + head = notification_list_get_next(head); + } + + notification_free_list(g_notification_list); + g_notification_list = new_noti_list; + } else { + g_notification_list = new_noti_list; + } +} +#endif + +static void _quickpanel_noti_clear_ongoinglist(Evas_Object *list) +{ + if (!list) + return; + + if (!ongoing_first) + return; + + quickpanel_list_util_item_del_by_type(list, ongoing_first, + QP_ITEM_TYPE_ONGOING_NOTI); +} + +static void _quickpanel_noti_clear_notilist(Evas_Object *list) +{ + if (!list) + return; + + if (!g_noti_gridbox) + return; + + if (g_noti_gridbox != NULL) { + gridbox_remove(g_noti_gridbox); + g_noti_gridbox = NULL; + } + if (noti_first != NULL) { + elm_object_item_del(noti_first); + noti_first= NULL; + } + if (noti_group != NULL) { + elm_object_item_del(noti_group); + noti_group= NULL; + } +} + +static void _quickpanel_noti_clear_list_all(Evas_Object *list) +{ + _quickpanel_noti_clear_ongoinglist(list); + ongoing_first = NULL; + + _quickpanel_noti_clear_notilist(list); +} + +static void _quickpanel_noti_ongoing_add(Evas_Object *list, void *data) +{ + qp_item_data *qid = NULL; + Elm_Object_Item *it = NULL; + + if (!list) + return; + + qid = quickpanel_list_util_item_new(QP_ITEM_TYPE_ONGOING_NOTI, data); + if (!qid) + return; + +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + it = quickpanel_list_util_sort_insert(list, itc_ongoing, qid, NULL, + ELM_GENLIST_ITEM_NONE, quickpanel_noti_select_cb, qid); +#else + it = quickpanel_list_util_sort_insert(list, itc_ongoing, qid, NULL, + ELM_GENLIST_ITEM_NONE, quickpanel_noti_select_cb, data); +#endif + + if (it) { + ongoing_first = it; +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + noti_node_add(g_noti_node, (void *)data, (void *)it); +#endif + } + else + ERR("fail to insert item to list : %p", data); + + DBG("noti ongoing[%p] data[%p] added, it[%p]", qid, data, it); +} + +static void _quickpanel_noti_group_add(Evas_Object *list, void *data) +{ + qp_item_data *qid = NULL; + Elm_Object_Item *it = NULL; + + if (!list) + return; + + qid = quickpanel_list_util_item_new(QP_ITEM_TYPE_NOTI_GROUP, data); + if (!qid) + return; + + it = quickpanel_list_util_sort_insert(list, g_itc, qid, NULL, + ELM_GENLIST_ITEM_GROUP, NULL, NULL); + + if (it) + noti_group = it; + else + ERR("fail to insert item to list : %p", data); + + DBG("noti group[%p] data[%p] added, it[%p]", qid, data, it); +} + +void _quickpanel_noti_box_deleted_cb(void *data, Evas_Object *obj) { + DBG("deleting:%p", obj); + + int priv_id = -1; + + retif(data == NULL, , "Invalid parameter!"); + retif(obj == NULL, , "Invalid parameter!"); + + noti_node_item *item = data; + notification_h noti = item->noti; + + if (noti != NULL) { + notification_get_id(noti, NULL, &priv_id); + noti_node_remove(g_noti_node, priv_id); + } +} + +static void _quickpanel_noti_noti_add(Evas_Object *list, void *data, int is_prepend) +{ + retif(list == NULL, , "Invalid parameter!"); + qp_item_data *qid = NULL; + Elm_Object_Item *it = NULL; + notification_h noti = data; + notification_ly_type_e layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE; + + qid = quickpanel_list_util_item_new(QP_ITEM_TYPE_NOTI, NULL); + retif(qid == NULL, , "Invalid parameter!"); + + if (!noti_group) + _quickpanel_noti_group_add(list, NULL); + +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + if (noti_first == NULL) { + if (g_noti_gridbox == NULL) { + g_noti_gridbox = gridbox_create(list, quickpanel_get_app_data()); + gridbox_set_item_deleted_cb(g_noti_gridbox, _quickpanel_noti_box_deleted_cb); + } + + it = quickpanel_list_util_sort_insert(list, itc_noti, qid, noti_group, + ELM_GENLIST_ITEM_NONE, NULL, qid); + noti_first = it; + } +#else + it = quickpanel_list_util_sort_insert(list, itc_noti, qid, noti_group, + ELM_GENLIST_ITEM_NONE, quickpanel_noti_select_cb, data); +#endif + + if (noti != NULL) { + notification_get_layout(noti, &layout); + } + Evas_Object *noti_box = noti_box_create(list, layout); + + if (noti_box != NULL) { +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + noti_node_item *item = noti_node_add(g_noti_node, (void*)data, (void*)noti_box); + if (item != NULL) { + noti_box_node_set(noti_box, item); + noti_box_set_item_selected_cb(noti_box, quickpanel_notibox_select_cb); + noti_box_set_item_deleted_cb(noti_box, quickpanel_notibox_delete_cb); + gridbox_add_item(g_noti_gridbox, noti_box, is_prepend); + } +#endif + } else + ERR("fail to insert item to list : %p", data); + + DBG("noti[%p] data[%p] added, it[%p] of gridbox[%p]", + qid, data, noti_box, g_noti_gridbox); +} + + +void _quickpanel_noti_update_notilist(struct appdata *ad) +{ + Evas_Object *list = NULL; + notification_h noti = NULL; + notification_h noti_save = NULL; + notification_list_h get_list = NULL; + int applist = NOTIFICATION_DISPLAY_APP_ALL; + + DBG(""); + + retif(ad == NULL, , "Invalid parameter!"); + + list = ad->list; + retif(list == NULL, , "Failed to get noti genlist."); + +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + _quickpanel_noti_clear_list_all(list); + + notification_get_list(NOTIFICATION_TYPE_ONGOING, -1, &get_list); + while (get_list != NULL) { + noti = notification_list_get_data(get_list); + notification_get_display_applist(noti, &applist); + + if (applist & + NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY) { + notification_clone(noti, ¬i_save); + _quickpanel_noti_ongoing_add(list, noti_save); + } + get_list = notification_list_get_next(get_list); + } + notification_free_list(get_list); + + notification_get_list(NOTIFICATION_TYPE_NOTI , -1, &get_list); + while (get_list != NULL) { + noti = notification_list_get_data(get_list); + notification_get_display_applist(noti, &applist); + + if (applist & + NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY) { + notification_clone(noti, ¬i_save); + _quickpanel_noti_noti_add(list, noti_save, GRIDBOX_APPEND); + } + get_list = notification_list_get_next(get_list); + } + notification_free_list(get_list); + + if (g_noti_gridbox != NULL) { + elm_box_recalculate(g_noti_gridbox); + } +#else + /* Clear genlist */ + _quickpanel_noti_clear_list_all(list); + + /* Update notification list */ + if (ad->show_setting) + _quickpanel_noti_get_new_divided_list(); + else + _quickpanel_noti_get_new_list(); + + /* append ongoing data to genlist */ + if (g_notification_ongoing_list) { + get_list = + notification_list_get_tail(g_notification_ongoing_list); + noti = notification_list_get_data(get_list); + + while (get_list != NULL) { + notification_get_display_applist(noti, &applist); + + if (applist & + NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY) { + _quickpanel_noti_ongoing_add(list, noti); + } + + get_list = notification_list_get_prev(get_list); + noti = notification_list_get_data(get_list); + } + } + + /* append noti data to genlist */ + if (g_notification_list) { + get_list = notification_list_get_tail(g_notification_list); + noti = notification_list_get_data(get_list); + + while (get_list != NULL) { + notification_get_display_applist(noti, &applist); + + if (applist & NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY) + _quickpanel_noti_noti_add(list, noti, GRIDBOX_PREPEND); + + get_list = notification_list_get_prev(get_list); + noti = notification_list_get_data(get_list); + } + } +#endif +} + +static void _quickpanel_noti_delete_volatil_data(void) +{ + notification_list_h noti_list = NULL; + notification_list_h noti_list_head = NULL; + notification_h noti = NULL; + int property = 0; + + notification_get_grouping_list(NOTIFICATION_TYPE_NONE, -1, ¬i_list); + + noti_list_head = noti_list; + + while (noti_list != NULL) { + noti = notification_list_get_data(noti_list); + notification_get_property(noti, &property); + + if (property & NOTIFICATION_PROP_VOLATILE_DISPLAY) { + notification_set_property(noti, + property | + NOTIFICATION_PROP_DISABLE_UPDATE_ON_DELETE); + notification_delete(noti); + } + + noti_list = notification_list_get_next(noti_list); + } + + notification_free_list(noti_list_head); + + notification_update(NULL); +} + +static void _quickpanel_noti_detailed_changed_cb(void *data, notification_type_e type, notification_op *op_list, int num_op) +{ + int i = 0; + int op_type = 0; + int priv_id = 0; + struct appdata *ad = NULL; + notification_h new_noti = NULL; + notification_type_e noti_type = NOTIFICATION_TYPE_NONE; + int noti_applist = NOTIFICATION_DISPLAY_APP_ALL; + notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE; + + retif(data == NULL, , "Invalid parameter!"); + ad = data; + + DBG("test detailed quickpanel:%d", num_op); + + for (i = 0; i < num_op; i++) { + notification_op_get_data(op_list + i, NOTIFICATION_OP_DATA_TYPE, &op_type); + DBG("op_type:%d", op_type); + notification_op_get_data(op_list + i, NOTIFICATION_OP_DATA_PRIV_ID, &priv_id); + DBG("op_priv_id:%d", priv_id); + + if (op_type == NOTIFICATION_OP_INSERT) { + new_noti = notification_load(NULL, priv_id); + if (new_noti == NULL) continue; + + notification_get_type(new_noti, ¬i_type); + notification_get_display_applist(new_noti, ¬i_applist); + notification_get_layout(new_noti, ¬i_layout); + + DBG("layout:%d", noti_layout); + + if (noti_applist & NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY) { + noti_node_item *node = noti_node_get(g_noti_node, priv_id); + if (node != NULL) { + if (noti_type == NOTIFICATION_TYPE_NOTI) { + DBG("cb after inserted:%d", priv_id); + } + } else { + if (noti_type == NOTIFICATION_TYPE_NOTI) { + _quickpanel_noti_noti_add(ad->list, new_noti, GRIDBOX_PREPEND); + } else if (noti_type == NOTIFICATION_TYPE_ONGOING) { + _quickpanel_noti_ongoing_add(ad->list, new_noti); + } + } + DBG("%d noti added", priv_id); + } else { + notification_free(new_noti); + } + } + if (op_type == NOTIFICATION_OP_DELETE) { + noti_node_item *node = noti_node_get(g_noti_node, priv_id); + + if (node != NULL && node->noti != NULL) { + notification_h noti = node->noti; + notification_get_type(noti, ¬i_type); + + if (noti_type == NOTIFICATION_TYPE_NOTI) { + gridbox_remove_item(g_noti_gridbox, node->view, 0); + } else if (noti_type == NOTIFICATION_TYPE_ONGOING) { + elm_object_item_del(node->view); + } + } + DBG("%d noti deleted", priv_id); + } + if (op_type == NOTIFICATION_OP_UPDATE) { + noti_node_item *node = noti_node_get(g_noti_node, priv_id); + qp_item_data *qid = NULL; + notification_h old_noti = NULL; + + new_noti = notification_load(NULL, priv_id); + retif(new_noti == NULL, , "fail to load updated noti"); + + if (node != NULL && node->view != NULL && node->noti != NULL) { + notification_get_type(new_noti, ¬i_type); + + if (noti_type == NOTIFICATION_TYPE_NOTI) { + gridbox_remove_item(g_noti_gridbox, node->view, 0); + _quickpanel_noti_noti_add(ad->list, new_noti, GRIDBOX_PREPEND); +/* + gridbox_remove_and_add_item(g_noti_gridbox, node->view, + _quickpanel_noti_noti_add + ,ad->list, new_noti, GRIDBOX_PREPEND); +*/ + } else if (noti_type == NOTIFICATION_TYPE_ONGOING) { + old_noti = node->noti; + node->noti = new_noti; + + qid = elm_object_item_data_get(node->view); + retif(qid == NULL, , "noti is already deleted"); + quickpanel_list_util_item_set_data(qid, new_noti); + elm_genlist_item_fields_update(node->view, "*", + ELM_GENLIST_ITEM_FIELD_ALL); + } + + if (old_noti != NULL) { + notification_free(old_noti); + } + } else { + notification_get_display_applist(new_noti, ¬i_applist); + + if (noti_applist & NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY) { + + if (noti_type == NOTIFICATION_TYPE_NOTI) { + _quickpanel_noti_noti_add(ad->list, new_noti, GRIDBOX_PREPEND); + } else if (noti_type == NOTIFICATION_TYPE_ONGOING) { + _quickpanel_noti_ongoing_add(ad->list, new_noti); + } + } + } + + DBG("%d noti updated", priv_id); + } + } + + if (noti_node_get_item_count(g_noti_node, NOTIFICATION_TYPE_NOTI) + <= 0) { + struct appdata *ad = quickpanel_get_app_data(); + _quickpanel_noti_clear_notilist(ad->list); + } else { + if (noti_group != NULL) { + elm_genlist_item_fields_update(noti_group, "*", + ELM_GENLIST_ITEM_FIELD_ALL); + } + _quickpanel_noti_update_notibox(); + } +} + +static void _quickpanel_noti_update_sim_status_cb(keynode_t *node, void *data) +{ + struct appdata *ad = data; + + if (ad != NULL && ad->list != NULL) { + _quickpanel_noti_update_notilist(ad); + + _quickpanel_noti_update_notibox(); + } +} + +static int _quickpanel_noti_register_event_handler(struct appdata *ad) +{ + int ret = 0; + retif(ad == NULL, QP_FAIL, "Invalid parameter!"); + + /* Add dbus signal */ + e_dbus_init(); + ad->dbus_connection = e_dbus_bus_get(DBUS_BUS_SYSTEM); + if (ad->dbus_connection == NULL) { + ERR("noti register : failed to get dbus bus"); + return -1; + } + + ad->dbus_handler_size = + e_dbus_signal_handler_add(ad->dbus_connection, NULL, + QP_NOTI_ONGOING_DBUS_PATH, + QP_NOTI_ONGOING_DBUS_INTERFACE, "update_progress", + _quickpanel_noti_item_progress_update_cb, + ad); + if (ad->dbus_handler_size == NULL) + ERR("fail to add size signal"); + + ad->dbus_handler_progress = + e_dbus_signal_handler_add(ad->dbus_connection, NULL, + QP_NOTI_ONGOING_DBUS_PATH, + QP_NOTI_ONGOING_DBUS_INTERFACE, "update_size", + _quickpanel_noti_item_size_update_cb, + ad); + if (ad->dbus_handler_progress == NULL) + ERR("fail to add progress signal"); + + ad->dbus_handler_content = + e_dbus_signal_handler_add(ad->dbus_connection, NULL, + QP_NOTI_ONGOING_DBUS_PATH, + QP_NOTI_ONGOING_DBUS_INTERFACE, "update_content", + _quickpanel_noti_item_content_update_cb, + ad); + if (ad->dbus_handler_content == NULL) + ERR("fail to add content signal"); + + /* Notify vconf key */ + ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT, + _quickpanel_noti_update_sim_status_cb, + (void *)ad); + if (ret != 0) + ERR("Failed to register SIM_SLOT change callback!"); + + /* Register notification changed cb */ +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + notification_register_detailed_changed_cb(_quickpanel_noti_detailed_changed_cb, ad); +#else + notification_resister_changed_cb(_quickpanel_noti_changed_cb, ad); +#endif + + return ret; +} + +static int _quickpanel_noti_unregister_event_handler(struct appdata *ad) +{ + int ret = 0; + + /* Unregister notification changed cb */ +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + notification_unregister_detailed_changed_cb(_quickpanel_noti_detailed_changed_cb, (void *)ad); +#else + notification_unresister_changed_cb(_quickpanel_noti_changed_cb); +#endif + + /* Ignore vconf key */ + ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT, + _quickpanel_noti_update_sim_status_cb); + if (ret != 0) + ERR("Failed to ignore SIM_SLOT change callback!"); + + /* Delete dbus signal */ + if (ad->dbus_handler_size != NULL) { + e_dbus_signal_handler_del(ad->dbus_connection, + ad->dbus_handler_size); + ad->dbus_handler_size = NULL; + } + if (ad->dbus_handler_progress != NULL) { + e_dbus_signal_handler_del(ad->dbus_connection, + ad->dbus_handler_progress); + ad->dbus_handler_progress = NULL; + } + if (ad->dbus_handler_content != NULL) { + e_dbus_signal_handler_del(ad->dbus_connection, + ad->dbus_handler_content); + ad->dbus_handler_content = NULL; + } + + if (ad->dbus_connection != NULL) { + e_dbus_connection_close(ad->dbus_connection); + ad->dbus_connection = NULL; + } + + return QP_OK; +} + +static int _quickpanel_noti_check_first_start(void) +{ + int status = 0; + int ret = 0; + + ret = vconf_get_bool(VCONFKEY_QUICKPANEL_STARTED, &status); + if (ret) { + INFO("fail to get %s", VCONFKEY_QUICKPANEL_STARTED); + /* reboot */ + ret = vconf_set_bool(VCONFKEY_QUICKPANEL_STARTED, 1); + INFO("set : %s, result : %d", VCONFKEY_QUICKPANEL_STARTED, ret); + } + + if (status) + return 0; + + return 1; +} + +static Eina_Bool quickpanel_noti_refresh_gridbox(void *data) +{ + struct appdata *ad = NULL; + + retif(data == NULL, EINA_FALSE, "Invalid parameter!"); + ad = data; + + DBG("wr"); + + /* Update notification list */ + _quickpanel_noti_update_notilist(ad); + + _quickpanel_noti_register_event_handler(ad); + + _quickpanel_noti_update_notibox(); + + return EINA_FALSE; +} + +static int quickpanel_noti_init(void *data) +{ + struct appdata *ad = data; + int is_first = 0; + + retif(ad == NULL, QP_FAIL, "Invalid parameter!"); + + g_window = ad->win; + +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + noti_node_create(&g_noti_node); +#endif + + is_first = _quickpanel_noti_check_first_start(); + if (is_first) { + /* Remove ongoing and volatile noti data */ + notifiation_clear(NOTIFICATION_TYPE_ONGOING); + _quickpanel_noti_delete_volatil_data(); + } + + _quickpanel_noti_gl_style_init(); + + ecore_timer_add(0.200, quickpanel_noti_refresh_gridbox, ad); + + return QP_OK; +} + +static int quickpanel_noti_fini(void *data) +{ + struct appdata *ad = data; + retif(ad == NULL, QP_FAIL, "Invalid parameter!"); +#ifdef QP_DETAILED_NOTI_CHANGE_CB_ENABLE + if (g_noti_node != NULL) { + noti_node_destroy(&g_noti_node); + } +#else + /* Remove notification list */ + if (g_notification_ongoing_list != NULL) { + notification_free_list(g_notification_ongoing_list); + + g_notification_ongoing_list = NULL; + } + + if (g_notification_list != NULL) { + notification_free_list(g_notification_list); + + g_notification_list = NULL; + } +#endif + /* Unregister event handler */ + _quickpanel_noti_unregister_event_handler(data); + _quickpanel_noti_clear_list_all(ad->list); + _quickpanel_noti_gl_style_fini(); + return QP_OK; +} + +static int quickpanel_noti_suspend(void *data) +{ + struct appdata *ad = data; + retif(ad == NULL, QP_FAIL, "Invalid parameter!"); + + suspended = 1; + + if (ad->list) { + _quickpanel_noti_ani_image_control(EINA_FALSE); + } + + return QP_OK; +} + +static int quickpanel_noti_resume(void *data) +{ + struct appdata *ad = data; + retif(ad == NULL, QP_FAIL, "Invalid parameter!"); + + suspended = 0; + + if (ad->list) { + quickpanel_list_util_item_update_by_type(ad->list, + ongoing_first, QP_ITEM_TYPE_ONGOING_NOTI); + + _quickpanel_noti_ani_image_control(EINA_TRUE); + + _quickpanel_noti_update_notibox(); + } + + return QP_OK; +} + +static void quickpanel_noti_refresh(void *data) { + struct appdata *ad = NULL; + + retif(data == NULL, , "Invalid parameter!"); + ad = data; + + if (g_noti_gridbox != NULL) { + gridbox_rotation(g_noti_gridbox, ad->angle); + } + _quickpanel_noti_update_notibox(); +} + +void quickpanel_noti_lang_changed(void *data) +{ + struct appdata *ad = data; + + retif(ad == NULL, , "Invalid parameter!"); + + _quickpanel_noti_update_notilist(ad); + + _quickpanel_noti_update_notibox(); +} + +static unsigned int quickpanel_noti_get_height(void *data) +{ + int height = 0; + struct appdata *ad = data; + + retif(ad == NULL, 0, "Invalid parameter!"); + + if (noti_group) { + height = QP_THEME_LIST_ITEM_GROUP_HEIGHT; + } + height += + noti_node_get_item_count( + g_noti_node, + NOTIFICATION_TYPE_NOTI) * QP_THEME_LIST_ITEM_NOTI_HEIGHT + + noti_node_get_item_count(g_noti_node, NOTIFICATION_TYPE_ONGOING) * (QP_THEME_LIST_ITEM_ONGOING_HEIGHT + QP_THEME_LIST_ITEM_ONGOING_SEPERATOR_HEIGHT);return + height * ad->scale; +} diff --git a/daemon/notifications/noti.h b/daemon/notifications/noti.h new file mode 100755 index 0000000..9a31a1f --- /dev/null +++ b/daemon/notifications/noti.h @@ -0,0 +1,20 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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. + */ + +#ifndef __NOTI_H__ +#define __NOTI_H__ +char *quickpanel_noti_get_time(time_t t, char *buf, int buf_len); +#endif diff --git a/daemon/notifications/noti_box.c b/daemon/notifications/noti_box.c new file mode 100755 index 0000000..fae1be9 --- /dev/null +++ b/daemon/notifications/noti_box.c @@ -0,0 +1,480 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <string.h> +#include <Ecore_X.h> + +#include "quickpanel-ui.h" +#include "common.h" +#include "list_util.h" +#include "quickpanel_theme_def.h" +#include "noti_box.h" +#include "noti_node.h" +#include "noti.h" + +static void _noti_box_call_item_cb(Evas_Object *noti_box, const char *emission) { + retif(noti_box == NULL, , "invalid parameter"); + retif(emission == NULL, , "invalid parameter"); + + DBG("%s", emission); + + void (*cb)(void *data, Evas_Object *obj) = NULL; + noti_box_h *data = NULL; + + data = evas_object_data_get(noti_box, E_DATA_NOTI_BOX_H); + + if (strncmp(emission,"selected", strlen("selected")) == 0) { + cb = evas_object_data_get(noti_box, E_DATA_CB_SELECTED_ITEM); + + if (cb != NULL && data != NULL) { + cb(data->data, noti_box); + } + } + if (strncmp(emission,"deleted", strlen("deleted")) == 0) { + cb = evas_object_data_get(noti_box, E_DATA_CB_DELETED_ITEM); + + if (cb != NULL && data != NULL) { + cb(data->data, noti_box); + } + } +} + +void _signal_cb(void *data, Evas_Object *o, const char *emission, const char *source) +{ + retif(data == NULL, , "invalid parameter"); + retif(o == NULL, , "invalid parameter"); + retif(emission == NULL, , "invalid parameter"); + + _noti_box_call_item_cb(o, emission); +} + +Evas_Object *noti_box_create(Evas_Object *parent, notification_ly_type_e layout) { + Evas_Object *box = NULL; + + box = elm_layout_add(parent); + + DBG(""); + if (layout == NOTIFICATION_LY_NOTI_EVENT_SINGLE + || layout == NOTIFICATION_LY_NOTI_EVENT_MULTIPLE) { + elm_layout_file_set(box, DEFAULT_EDJ, + "quickpanel/notibox/single_multi"); + } else if (layout == NOTIFICATION_LY_NOTI_THUMBNAIL) { + elm_layout_file_set(box, DEFAULT_EDJ, "quickpanel/notibox/thumbnail"); + } else { + elm_layout_file_set(box, DEFAULT_EDJ, + "quickpanel/notibox/single_multi"); + } + + evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(box); + + noti_box_h *box_h = (noti_box_h *) malloc(sizeof(noti_box_h)); + box_h->layout = layout; + box_h->status = STATE_NORMAL; + box_h->data = NULL; + evas_object_data_set(box, E_DATA_NOTI_BOX_H, box_h); + DBG("created box:%p", box); + + //add event + elm_object_signal_callback_add(box, + "selected", + "object.layer.touch", + _signal_cb, + parent + ); + //add event + elm_object_signal_callback_add(box, + "deleted", + "object.layer.touch", + _signal_cb, + parent + ); + + return box; +} + +static void _set_image(Evas_Object *noti_box, notification_h noti, + notification_image_type_e image_type, const char *part, int is_stretch) { + + DBG(""); + + char *image = NULL; + + notification_get_image(noti, image_type, &image); + + if (image != NULL) { + Evas_Object *content = NULL; + content = elm_image_add(noti_box); + elm_image_file_set(content, image, NULL); + if (is_stretch == 1) { + elm_image_aspect_fixed_set(content, EINA_FALSE); + elm_image_resizable_set(content, EINA_TRUE, EINA_TRUE); + } + + elm_object_part_content_set(noti_box, part, content); + } +} + +static int _set_text(Evas_Object *noti_box, notification_h noti, + notification_text_type_e text_type, const char *part) { + char buf[128] = { 0, }; + + char *text = NULL; + time_t time = 0; + + if (notification_get_time_from_text(noti, text_type, &time) == NOTIFICATION_ERROR_NONE) { + if ((int)time > 0) { + quickpanel_noti_get_time(time, buf, sizeof(buf)); + text = buf; + } + } else { + notification_get_text(noti, text_type, &text); + } + + if (text != NULL) { + elm_object_part_text_set(noti_box, part, text); + + return strlen(text); + } + + return 0; +} + +static int _check_text_null(notification_h noti, + notification_text_type_e text_type) { + DBG(""); + + char *text = NULL; + + notification_get_text(noti, text_type, &text); + + if (text == NULL) { + return 1; + } + + return 0; +} + +static int _check_image_null(notification_h noti, + notification_image_type_e image_type) { + DBG(""); + + char *image = NULL; + + notification_get_image(noti, image_type, &image); + + if (image == NULL) { + return 1; + } + + return 0; +} + +static void _noti_box_set_layout_single(Evas_Object *noti_box, + notification_h noti) { + DBG(""); + + char *dir = NULL; + char *domain = NULL; + + notification_get_text_domain(noti, &domain, &dir); + if (domain != NULL && dir != NULL) + bindtextdomain(domain, dir); + + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_TITLE, + "object.text.title"); + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_CONTENT, + "object.text.contents"); + + if (_check_text_null(noti, NOTIFICATION_TEXT_TYPE_INFO_1) == 0) { + if (_check_text_null(noti, NOTIFICATION_TEXT_TYPE_INFO_SUB_1) == 1) { + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_INFO_1, + "object.text.info.1"); + } else { + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_INFO_1, + "object.text.info.1.short"); + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_INFO_SUB_1, + "object.text.info.sub.1"); + } + } + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_INFO_2, + "object.text.info.2"); + + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL) == 0) { + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_ICON, + "object.icon.sub", 1); + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL, + "object.icon", 1); + } else { + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_ICON, + "object.icon", 1); + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_ICON_SUB, + "object.icon.sub", 1); + } + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_BACKGROUND, + "object.icon.background", 1); + + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_BACKGROUND) == 0) { + elm_object_signal_emit(noti_box, "box.show.dim", "box.prog"); + } + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_ICON) == 1 + && _check_image_null(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL) == 1) { + elm_object_signal_emit(noti_box, "box.hide.icon.bg", "box.prog"); + } + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_ICON_SUB) == 0 + || _check_image_null(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL) == 0) { + elm_object_signal_emit(noti_box, "box.show.sub.bg", "box.prog"); + } +} + +static void _noti_box_set_layout_multi(Evas_Object *noti_box, + notification_h noti) { + DBG(""); + + int length = 0; + char *dir = NULL; + char *domain = NULL; + char buf[128] = {0,}; + + notification_get_text_domain(noti, &domain, &dir); + if (domain != NULL && dir != NULL) + bindtextdomain(domain, dir); + + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_TITLE, + "object.text.title"); + if (_check_text_null(noti, NOTIFICATION_TEXT_TYPE_EVENT_COUNT) == 0) { + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_CONTENT, + "object.text.contents.short"); + length = _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, + "object.text.count"); + length = (length >= 5) ? 5 : length; + snprintf(buf, sizeof(buf), "box.count.%d", length); + elm_object_signal_emit(noti_box, buf, "box.prog"); + DBG("buf:%s", buf); + } else { + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_CONTENT, + "object.text.contents"); + } + + if (_check_text_null(noti, NOTIFICATION_TEXT_TYPE_INFO_1) == 0) { + if (_check_text_null(noti, NOTIFICATION_TEXT_TYPE_INFO_SUB_1) == 1) { + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_INFO_1, + "object.text.info.1"); + } else { + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_INFO_1, + "object.text.info.1.short"); + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_INFO_SUB_1, + "object.text.info.sub.1"); + } + } + if (_check_text_null(noti, NOTIFICATION_TEXT_TYPE_INFO_2) == 0) { + if (_check_text_null(noti, NOTIFICATION_TEXT_TYPE_INFO_SUB_2) == 1) { + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_INFO_2, + "object.text.info.2"); + } else { + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_INFO_2, + "object.text.info.2.short"); + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_INFO_SUB_2, + "object.text.info.sub.2"); + } + } + + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL) == 0) { + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_ICON, + "object.icon.sub", 1); + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL, + "object.icon", 1); + } else { + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_ICON, + "object.icon", 1); + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_ICON_SUB, + "object.icon.sub", 1); + } + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_BACKGROUND, + "object.icon.background", 1); + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_BACKGROUND) == 0) { + elm_object_signal_emit(noti_box, "box.show.dim", "box.prog"); + } + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_ICON) == 1 + && _check_image_null(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL) == 1) { + elm_object_signal_emit(noti_box, "box.hide.icon.bg", "box.prog"); + } + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_ICON_SUB) == 0 + || _check_image_null(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL) == 0) { + elm_object_signal_emit(noti_box, "box.show.sub.bg", "box.prog"); + } +} + +static void _noti_box_set_layout_thumbnail(Evas_Object *noti_box, + notification_h noti) { + DBG(""); + + char *dir = NULL; + char *domain = NULL; + + notification_get_text_domain(noti, &domain, &dir); + if (domain != NULL && dir != NULL) + bindtextdomain(domain, dir); + + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_TITLE, + "object.text.title"); + _set_text(noti_box, noti, NOTIFICATION_TEXT_TYPE_CONTENT, + "object.text.contents"); + + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL) == 0) { + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_ICON, + "object.icon.sub", 0); + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL, + "object.icon", 0); + } else { + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_ICON, + "object.icon", 0); + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_ICON_SUB, + "object.icon.sub", 0); + } + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_BACKGROUND, + "object.icon.background", 1); + + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_LIST_1, + "object.thumbnail.list.1", 1); + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_LIST_2, + "object.thumbnail.list.2", 1); + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_LIST_3, + "object.thumbnail.list.3", 1); + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_LIST_4, + "object.thumbnail.list.4", 1); + _set_image(noti_box, noti, NOTIFICATION_IMAGE_TYPE_LIST_5, + "object.thumbnail.list.5", 1); + + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_BACKGROUND) == 0) { + elm_object_signal_emit(noti_box, "box.show.dim", "box.prog"); + } + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_ICON) == 1 + && _check_image_null(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL) == 1) { + elm_object_signal_emit(noti_box, "box.hide.icon.bg", "box.prog"); + } + if (_check_image_null(noti, NOTIFICATION_IMAGE_TYPE_ICON_SUB) == 0 + || _check_image_null(noti, NOTIFICATION_IMAGE_TYPE_THUMBNAIL) == 0) { + elm_object_signal_emit(noti_box, "box.show.sub.bg", "box.prog"); + } +} + +static void _noti_box_set_layout(Evas_Object *noti_box, notification_h noti, + notification_ly_type_e layout) { + + DBG("layout:%d", layout); + + switch (layout) { + case NOTIFICATION_LY_NOTI_EVENT_SINGLE: + _noti_box_set_layout_single(noti_box, noti); + break; + case NOTIFICATION_LY_NOTI_EVENT_MULTIPLE: + _noti_box_set_layout_multi(noti_box, noti); + break; + case NOTIFICATION_LY_NOTI_THUMBNAIL: + _noti_box_set_layout_thumbnail(noti_box, noti); + break; + case NOTIFICATION_LY_NONE: + case NOTIFICATION_LY_ONGOING_EVENT: + case NOTIFICATION_LY_ONGOING_PROGRESS: + case NOTIFICATION_LY_MAX: + DBG("not supported layout type:%d", layout); + break; + } +} + +void noti_box_remove(Evas_Object *noti_box) { + + retif(noti_box == NULL, , "invalid parameter"); + + noti_box_h *noti_box_h = evas_object_data_get(noti_box, E_DATA_NOTI_BOX_H); + + if (noti_box_h != NULL) + free(noti_box_h); + + evas_object_data_del(noti_box, E_DATA_NOTI_BOX_H); + evas_object_data_del(noti_box, E_DATA_CB_SELECTED_ITEM); + evas_object_data_del(noti_box, E_DATA_CB_DELETED_ITEM); + + evas_object_del(noti_box); +} + +void noti_box_set_status(Evas_Object *noti_box, int status) { + retif(noti_box == NULL, , "invalid parameter"); + + noti_box_h *noti_box_h = evas_object_data_get(noti_box, E_DATA_NOTI_BOX_H); + + if (noti_box_h != NULL) { + noti_box_h->status = status; + } +} + +int noti_box_get_status(Evas_Object *noti_box) { + retif(noti_box == NULL, STATE_NORMAL, "invalid parameter"); + + noti_box_h *noti_box_h = evas_object_data_get(noti_box, E_DATA_NOTI_BOX_H); + + if (noti_box_h != NULL) { + return noti_box_h->status; + } + + return STATE_DELETING; +} + +void noti_box_node_set(Evas_Object *noti_box, void *data) { + retif(noti_box == NULL, , "invalid parameter"); + retif(data == NULL, , "invalid parameter"); + + noti_box_h *noti_box_data = evas_object_data_get(noti_box, E_DATA_NOTI_BOX_H); + + if (noti_box_data != NULL) { + noti_box_data->data = data; + + if (data != NULL) { + noti_node_item *item = data; + _noti_box_set_layout(noti_box, item->noti, noti_box_data->layout); + } + } +} + +void *noti_box_node_get(Evas_Object *noti_box) { + retif(noti_box == NULL, NULL, "invalid parameter"); + + noti_box_h *noti_box_data = evas_object_data_get(noti_box, E_DATA_NOTI_BOX_H); + + if (noti_box_data != NULL) { + return noti_box_data->data; + } + + return NULL; +} + +void noti_box_set_item_selected_cb(Evas_Object *noti_box, + void(*selected_cb)(void *data, Evas_Object *obj)) { + retif(noti_box == NULL, , "invalid parameter"); + retif(selected_cb == NULL, , "invalid parameter"); + + evas_object_data_set(noti_box, E_DATA_CB_SELECTED_ITEM, selected_cb); +} + +void noti_box_set_item_deleted_cb(Evas_Object *noti_box, + void(*deleted_cb)(void *data, Evas_Object *obj)) { + retif(noti_box == NULL, , "invalid parameter"); + retif(deleted_cb == NULL, , "invalid parameter"); + + evas_object_data_set(noti_box, E_DATA_CB_DELETED_ITEM, deleted_cb); +} diff --git a/daemon/notifications/noti_box.h b/daemon/notifications/noti_box.h new file mode 100755 index 0000000..d5d8fd2 --- /dev/null +++ b/daemon/notifications/noti_box.h @@ -0,0 +1,46 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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. + */ + +#ifndef __QUICKPANEL_NOTI_BOX_H__ +#define __QUICKPANEL_NOTI_BOX_H__ + +#include <notification.h> + +#define STATE_NORMAL 1 +#define STATE_DELETING 0 + +#define E_DATA_NOTI_BOX_H "noti_box" +#define E_DATA_CB_SELECTED_ITEM "noti_box_cb_selected" +#define E_DATA_CB_DELETED_ITEM "noti_box_cb_deleted" + +typedef struct _noti_box_h { + int status; + void *data; + notification_ly_type_e layout; +} noti_box_h; + +Evas_Object *noti_box_create(Evas_Object *parent, notification_ly_type_e layout); +void noti_box_node_set(Evas_Object *noti_box, void *data); +void *noti_box_node_get(Evas_Object *noti_box); +void noti_box_remove(Evas_Object *noti_box); +void noti_box_set_item_selected_cb(Evas_Object *noti_box, + void(*selected_cb)(void *data, Evas_Object *obj)); +void noti_box_set_item_deleted_cb(Evas_Object *noti_box, + void(*deleted_cb)(void *data, Evas_Object *obj)); +int noti_box_get_status(Evas_Object *noti_box); +void noti_box_set_status(Evas_Object *noti_box, int status); + +#endif diff --git a/daemon/notifications/noti_display_app.c b/daemon/notifications/noti_display_app.c new file mode 100755 index 0000000..3c3d5bd --- /dev/null +++ b/daemon/notifications/noti_display_app.c @@ -0,0 +1,422 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <E_Notify.h> +#include <E_Notification_Daemon.h> +#include <Elementary.h> +#include "noti_win.h" +#include "quickpanel-ui.h" +#include "noti_display_app.h" + +#define INFO(str, args...) fprintf(stdout, str"\n", ##args) +#define ERR(str, args...) fprintf(stderr, str"\n", ##args) + +static E_Notification_Daemon *g_notification_daemon; +static const char *data_key = "_noti_data"; +static Evas_Object *app_win; + +struct Daemon_Data { + E_Notification_Daemon *daemon; + Eina_List *notes; + double default_timeout; + int next_id; +}; + +struct Timer_Data { + struct Daemon_Data *daemon_data; + E_Notification *n; + Ecore_Timer *timer; + enum Noti_Orient orient; +}; + +struct Noti_Data { + E_Notification *n; + const char *time; +}; + +/* Windows to display different orientations of notification */ +static Evas_Object *noti_win[NOTI_ORIENT_LAST]; + +Eina_List *notification_daemon_note_list_get() +{ + struct Daemon_Data *daemon_data; + + if (!g_notification_daemon) + return NULL; + daemon_data = e_notification_daemon_data_get(g_notification_daemon); + if (!daemon_data) + return NULL; + return daemon_data->notes; +} + +void notification_daemon_note_list_clear() +{ + struct Daemon_Data *daemon_data; + Eina_List *l; + E_Notification *n; + struct Noti_Data *noti_data; + + if (!g_notification_daemon) + return; + daemon_data = e_notification_daemon_data_get(g_notification_daemon); + if (!daemon_data) + return; + EINA_LIST_FOREACH(daemon_data->notes, l, noti_data) { + daemon_data->notes = eina_list_remove(daemon_data->notes, + noti_data); + n = noti_data->n; + eina_stringshare_replace(¬i_data->time, NULL); + e_notification_unref(n); + free(noti_data); + } +} + +static struct Noti_Data *_notification_daemon_noti_data_find( + struct Daemon_Data *daemon_data, E_Notification *n) +{ + Eina_List *l; + struct Noti_Data *noti_data; + + EINA_LIST_FOREACH(daemon_data->notes, l, noti_data) + if (noti_data->n == n) + return noti_data; + + return NULL; +} + +static void _notification_daemon_note_close(struct Daemon_Data *daemon_data, + E_Notification *n, int reason) +{ + struct Noti_Data *noti_data; + + noti_data = _notification_daemon_noti_data_find(daemon_data, n); + if (!noti_data) + return; + daemon_data->notes = eina_list_remove(daemon_data->notes, noti_data); + n = noti_data->n; + eina_stringshare_replace(¬i_data->time, NULL); + e_notification_unref(n); + free(noti_data); + e_notification_closed_set(n, 1); + e_notification_daemon_signal_notification_closed(daemon_data->daemon, + e_notification_id_get(n), reason); +} + +static void _note_destroy(struct Timer_Data *timer_data, + enum E_Notification_Closed_Reason reason) +{ + enum Noti_Orient orient; + + if (!timer_data) + return; + orient = timer_data->orient; + if (!e_notification_closed_get(timer_data->n)) + _notification_daemon_note_close(timer_data->daemon_data, + timer_data->n, + reason); + e_notification_unref(timer_data->n); + ecore_timer_del(timer_data->timer); + free(timer_data); + if (noti_win[orient]) { + evas_object_data_set(noti_win[orient], data_key, NULL); + evas_object_del(noti_win[orient]); + noti_win[orient] = NULL; + } +} + +Eina_Bool _note_close_timer_cb(void *data) +{ + _note_destroy(data, E_NOTIFICATION_CLOSED_EXPIRED); + return ECORE_CALLBACK_CANCEL; +} + +static E_Notification *_notification_daemon_note_open_find( + struct Daemon_Data *daemon_data, unsigned int id) +{ + Eina_List *l; + struct Noti_Data *noti_data; + + EINA_LIST_FOREACH(daemon_data->notes, l, noti_data) + if (e_notification_id_get(noti_data->n) == id) + return noti_data->n; + + return NULL; +} + +static void _notification_daemon_note_close_cb(E_Notification_Daemon *daemon, + unsigned int notification_id) +{ + struct Daemon_Data *daemon_data; + E_Notification *n; + + daemon_data = e_notification_daemon_data_get(daemon); + n = _notification_daemon_note_open_find(daemon_data, notification_id); + if (n) + _notification_daemon_note_close(daemon_data, n, + E_NOTIFICATION_CLOSED_REQUESTED); + /* else send error */ +} + + +static void _noti_hide_cb(void *data, Evas_Object *obj, + const char *emission, const char *source) +{ + _note_destroy(data, E_NOTIFICATION_CLOSED_DISMISSED); +} + +static void _noti_button_clicked_cb(void *data, Evas_Object *obj, + void *event_info) +{ + _note_destroy(data, E_NOTIFICATION_CLOSED_REQUESTED); +} + +static void _noti_show(E_Notification *n, enum Noti_Orient orient, + struct Timer_Data *timer_data) +{ + const char *summary; + Evas_Object *layout; + const char *path_icon; + Evas_Object *icon; + const char *data_win_height = NULL; + int noti_height = 50; + struct Timer_Data *old_timer_data = NULL; + Evas_Object *button = NULL; + + if (noti_win[orient]) { + old_timer_data = evas_object_data_get(noti_win[orient], + data_key); + _note_destroy(old_timer_data, E_NOTIFICATION_CLOSED_REQUESTED); + } + noti_win[orient] = noti_win_add(NULL); + evas_object_data_set(noti_win[orient], data_key, timer_data); + layout = elm_layout_add(noti_win[orient]); + /* Only for sample code the theme implementation for layout has been + used. Apps should implement this layout/edje object which can have + at least one TEXT/TEXT BLOCK for showing body of notification and one + swallow part for showing icon of the notification. + Optionally the summary can be shown as well. + Applications need to set the minimum height of the layout or edje object + using evas_object_size_hint_min_set which can be used by the + notification window to resize itself. + */ + if (orient == NOTI_ORIENT_BOTTOM) + elm_layout_theme_set(layout, "tickernoti", "base", "info"); + else { + elm_layout_theme_set(layout, "tickernoti", "base", + "default"); + button = elm_button_add(layout); + elm_object_style_set(button, "tickernoti"); + elm_object_text_set(button, _S("IDS_COM_BODY_CLOSE")); + elm_object_part_content_set(layout, "button", button); + evas_object_smart_callback_add(button, "clicked", + _noti_button_clicked_cb, timer_data); + } + elm_object_signal_callback_add(layout, "request,hide", "", + _noti_hide_cb, timer_data); + /* Getting the height of the layout from theme just for sample code. + App is free to use any other method. + */ + data_win_height = (char *)elm_layout_data_get(layout, "height"); + if (data_win_height != NULL && elm_config_scale_get() > 0.0) + noti_height = (int)(elm_config_scale_get() + * atoi(data_win_height)); + evas_object_size_hint_min_set(layout, 1, noti_height); + noti_win_content_set(noti_win[orient], layout); + summary = e_notification_summary_get(n); + if (summary) + elm_object_part_text_set(layout, "elm.text", summary); + else + elm_object_part_text_set(layout, "elm.text", + "new notification"); + path_icon = e_notification_app_icon_get(n); + if (path_icon) { + INFO("%s", path_icon); + icon = elm_image_add(layout); + if (elm_image_file_set(icon, path_icon, NULL)) { + elm_image_resizable_set(icon, EINA_TRUE, EINA_TRUE); + elm_object_part_content_set(layout, "icon", icon); + } + } + noti_win_orient_set(noti_win[orient], orient); + if (app_win) + elm_win_rotation_with_resize_set(noti_win[orient], + elm_win_rotation_get(app_win)); + evas_object_show(noti_win[orient]); +} + +void _notification_daemon_note_show(struct Daemon_Data *daemon_data, + E_Notification *n) +{ + int timeout; + const char *category; + enum Noti_Orient orient = NOTI_ORIENT_TOP; + struct Noti_Data *noti_data; + time_t current; + char buf[256]; + struct tm time_st; + struct Timer_Data *timer_data; + + category = e_notification_hint_category_get(n); + if (category) { + if (!strcmp("device", category)) + orient = NOTI_ORIENT_BOTTOM; + } + + noti_data = calloc(1, sizeof(struct Noti_Data)); + if (!noti_data) + return; + e_notification_ref(n); + noti_data->n = n; + current = time(NULL); + localtime_r(¤t, &time_st); + strftime(buf, sizeof(buf), "%I:%M %p", &time_st); + eina_stringshare_replace(¬i_data->time, buf); + daemon_data->notes = eina_list_append(daemon_data->notes, noti_data); + timeout = e_notification_timeout_get(n); + timer_data = calloc(1, sizeof(struct Timer_Data)); + _noti_show(n, orient, timer_data); + timer_data->daemon_data = daemon_data; + timer_data->orient = orient; + e_notification_ref(n); + e_notification_closed_set(n, 0); + timer_data->n = n; + timer_data->timer = ecore_timer_add(timeout == -1 ? + daemon_data->default_timeout : (float)timeout / 1000, + _note_close_timer_cb, timer_data); + + INFO("Received notification from %s:%s %s", + e_notification_app_name_get(n), + e_notification_summary_get(n), e_notification_body_get(n)); +} + +static int _notification_cb(E_Notification_Daemon *daemon, E_Notification *n) +{ + struct Daemon_Data *daemon_data; + unsigned int replaces_id; + unsigned int new_id; + + daemon_data = e_notification_daemon_data_get(daemon); + replaces_id = e_notification_replaces_id_get(n); + if (replaces_id) + new_id = replaces_id; + else + new_id = daemon_data->next_id++; + e_notification_id_set(n, new_id); + _notification_daemon_note_show(daemon_data, n); + return new_id; +} + +static Eina_Bool _init() +{ + Eina_Bool ret = EINA_FALSE; + struct Daemon_Data *daemon_data; + + if (!g_notification_daemon) { + e_notification_daemon_init(); + g_notification_daemon = e_notification_daemon_add("notification" + , "Enlightenment"); + if (!g_notification_daemon) { + ERR("Unable to add a notification daemon"); + return EINA_FALSE; + } + daemon_data = calloc(1, sizeof(struct Daemon_Data)); + if (!daemon_data) { + notification_daemon_shutdown(); + return EINA_FALSE; + } + daemon_data->default_timeout = 1.0; + daemon_data->daemon = g_notification_daemon; + e_notification_daemon_data_set(g_notification_daemon, + daemon_data); + e_notification_daemon_callback_notify_set(g_notification_daemon, + _notification_cb); + e_notification_daemon_callback_close_notification_set( + g_notification_daemon, + _notification_daemon_note_close_cb); + INFO("Initializing Notification Daemon"); + } + ret = !!g_notification_daemon; + return ret; +} + +static Eina_Bool _shutdown() +{ + struct Daemon_Data *daemon_data; + Eina_List *l; + E_Notification *n; + int i; + struct Noti_Data *noti_data; + Eina_Bool ret = EINA_FALSE; + + for (i = 0; i < NOTI_ORIENT_LAST; i++) + if (noti_win[i]) { + evas_object_del(noti_win[i]); + noti_win[i] = NULL; + } + if (!g_notification_daemon) + return ret; + daemon_data = e_notification_daemon_data_get( + g_notification_daemon); + if (!daemon_data) + return ret; + EINA_LIST_FOREACH(daemon_data->notes, l, noti_data) { + daemon_data->notes = eina_list_remove(daemon_data->notes, + noti_data); + n = noti_data->n; + eina_stringshare_replace(¬i_data->time, NULL); + e_notification_unref(n); + free(noti_data); + } + free(daemon_data); + e_notification_daemon_free(g_notification_daemon); + e_notification_daemon_shutdown(); + g_notification_daemon = NULL; + ret = EINA_TRUE; + return ret; +} + +void notification_daemon_init() +{ + int i; + + if (!_init()) { + ERR("Error in intializing the notification daemon"); + return; + } + for (i = 0; i < NOTI_ORIENT_LAST; i++) + if (noti_win[i]) { + evas_object_del(noti_win[i]); + noti_win[i] = NULL; + } +} + +void notification_daemon_win_set(Evas_Object *win) +{ + /* This window is used to detect the orientation of the receiver app + window to support rotation of the notification window. + */ + app_win = win; +} + +void notification_daemon_shutdown() +{ + if (!_shutdown()) { + ERR("Error in shutting down the notification daemon"); + return; + } + app_win = NULL; + INFO("Terminating Notification Daemon"); +} diff --git a/daemon/notifications/noti_display_app.h b/daemon/notifications/noti_display_app.h new file mode 100755 index 0000000..652ee43 --- /dev/null +++ b/daemon/notifications/noti_display_app.h @@ -0,0 +1,28 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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. + */ + +#ifndef __NOTI_DISPLAY_APP_H__ +#define __NOTI_DISPLAY_APP_H__ +#include <Elementary.h> + +/* Initializes the notification daemon */ +void notification_daemon_init(); +/* Sets the window which rotation will be used to rotate the notification popup +while displaying */ +void notification_daemon_win_set(Evas_Object *win); +/* Terminates the notification daemon */ +void notification_daemon_shutdown(); +#endif diff --git a/daemon/notifications/noti_gridbox.c b/daemon/notifications/noti_gridbox.c new file mode 100755 index 0000000..49e906c --- /dev/null +++ b/daemon/notifications/noti_gridbox.c @@ -0,0 +1,454 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <Ecore_X.h> + +#include "quickpanel-ui.h" +#include "common.h" +#include "list_util.h" +#include "quickpanel_theme_def.h" +#include "noti_gridbox.h" +#include "noti_box.h" + +#define E_DATA_LAYOUT_PORTRAIT "layout_portrait" +#define E_DATA_LAYOUT_LANDSCAPE "layout_landscape" +#define E_DATA_CB_DELETE_ITEM "cb_delete_item" +#define E_DATA_CB_REMOVED "cb_removed" +#define E_DATA_APP_DATA "app_data" + +typedef struct _gridbox_info_layout { + int n_per_rows; + int padding_top; + int padding_left; + int padding_right; + int padding_bottom; + int padding_between; + int child_w; + int child_h; + double scale; +} gridbox_info_layout; + +typedef struct _gridbox_info_animation { + Evas_Object *gridbox; + Evas_Object *item; + + void (*update_cb)(Evas_Object *list, void *data, int is_prepend); + Evas_Object *container; + void *noti; + int pos; +} gridbox_info_animation; + +static void _gridbox_layout_get_pos(int order, int *x, int *y, void *data) { + gridbox_info_layout *info_layout = data; + + retif(data == NULL, , "invalid parameter"); + retif(x == NULL, , "invalid parameter"); + retif(y == NULL, , "invalid parameter"); + + int n_per_row = info_layout->n_per_rows; + + int row = (order - 1) / n_per_row; + int column = (order - 1) - (row * n_per_row); + + //DBG("order:%d r:%d c:%d", order, row, column); + + int row_x = info_layout->padding_left + + ((info_layout->child_w + info_layout->padding_between) * column); + + int row_y = info_layout->padding_top + + ((info_layout->child_h + info_layout->padding_between) * row); + + *x = row_x; + *y = row_y; +} + +static void _gridbox_layout(Evas_Object *o, Evas_Object_Box_Data *priv, + void *data) { + int n_children; + int x, y, w, h; + int off_x = 0, off_y = 0; + Eina_List *l; + Eina_List *l_next; + Evas_Object_Box_Option *opt; + int child_w, child_h; + + retif(o == NULL, , "invalid parameter"); + retif(priv == NULL, , "invalid parameter"); + retif(data == NULL, , "invalid parameter"); + + gridbox_info_layout *info_layout = (gridbox_info_layout *) data; + + n_children = eina_list_count(priv->children); + DBG("layout function:%d", n_children); + DBG("ref count:%p(%d)",o, evas_object_ref_get(o)); + if (!n_children) { + return; + } + + //box geometry + evas_object_geometry_get(o, &x, &y, &w, &h); + + //set info about children + opt = eina_list_data_get(priv->children); + evas_object_size_hint_min_get(opt->obj, &child_w, &child_h); + + info_layout->child_w = child_w; + info_layout->child_h = child_h; + + DBG("grid layout children:%d %d", child_w, child_h); + + int order_children = 1; + EINA_LIST_FOREACH_SAFE(priv->children, l, l_next, opt) + { + _gridbox_layout_get_pos(order_children, &off_x, &off_y, info_layout); + evas_object_move(opt->obj, x + off_x, y + off_y); + evas_object_resize(opt->obj, info_layout->child_w, + info_layout->child_h); + order_children++; + } + + evas_object_size_hint_min_set(o, -1, + off_y + info_layout->child_h + info_layout->padding_bottom); +} + +Evas_Object *gridbox_create(Evas_Object *parent, void *data) { + + retif(parent == NULL, NULL, "invalid parameter"); + retif(data == NULL, NULL, "invalid parameter"); + struct appdata *ad = data; + Evas_Object *gridbox = NULL; + + gridbox_info_layout *info_layout_portrait = NULL; + gridbox_info_layout *info_layout_landscape = NULL; + + info_layout_portrait = (gridbox_info_layout *) malloc( + sizeof(gridbox_info_layout)); + retif(info_layout_portrait == NULL, NULL, "memory allocation failed"); + info_layout_portrait->padding_between = 12 * ad->scale; + info_layout_portrait->padding_top = 0; + info_layout_portrait->padding_left = 14 * ad->scale; + info_layout_portrait->padding_bottom = 12 * ad->scale; + info_layout_portrait->n_per_rows = 2; + info_layout_portrait->child_w = 0; //340; + info_layout_portrait->child_h = 0; //400; + info_layout_portrait->scale = ad->scale; + + info_layout_landscape = (gridbox_info_layout *) malloc( + sizeof(gridbox_info_layout)); + retif(info_layout_landscape == NULL, NULL, "memory allocation failed"); + info_layout_landscape->padding_between = 12 * ad->scale; + info_layout_landscape->padding_top = 0; + info_layout_landscape->padding_left = 14 * ad->scale; + info_layout_landscape->padding_bottom = 12 * ad->scale; + info_layout_landscape->n_per_rows = 3; + info_layout_landscape->child_w = 0; //409; + info_layout_landscape->child_h = 0; //400; + info_layout_landscape->scale = ad->scale; + + gridbox = elm_box_add(parent); + evas_object_size_hint_weight_set(gridbox, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(gridbox, EVAS_HINT_FILL, EVAS_HINT_FILL); + + if (ad->angle == 270 || ad->angle == 90) + elm_box_layout_set(gridbox, _gridbox_layout, info_layout_landscape, + NULL); + else + elm_box_layout_set(gridbox, _gridbox_layout, info_layout_portrait, + NULL); + + evas_object_ref(gridbox); + evas_object_show(gridbox); + + evas_object_data_set(gridbox, E_DATA_LAYOUT_PORTRAIT, info_layout_portrait); + evas_object_data_set(gridbox, E_DATA_LAYOUT_LANDSCAPE, + info_layout_landscape); + evas_object_data_set(gridbox, E_DATA_CB_DELETE_ITEM, NULL); + evas_object_data_set(gridbox, E_DATA_APP_DATA, ad); + + return gridbox; +} + +void gridbox_remove(Evas_Object *gridbox) { + + retif(gridbox == NULL, , "invalid parameter"); + + gridbox_info_layout *info_layout_portrait = evas_object_data_get(gridbox, + E_DATA_LAYOUT_PORTRAIT); + gridbox_info_layout *info_layout_landscape = evas_object_data_get(gridbox, + E_DATA_LAYOUT_LANDSCAPE); + + gridbox_remove_all_item(gridbox, 0); + evas_object_data_del(gridbox, E_DATA_LAYOUT_PORTRAIT); + evas_object_data_del(gridbox, E_DATA_LAYOUT_LANDSCAPE); + evas_object_data_del(gridbox, E_DATA_CB_DELETE_ITEM); + evas_object_data_del(gridbox, E_DATA_APP_DATA); + evas_object_unref(gridbox); + evas_object_del(gridbox); + + if (info_layout_portrait != NULL) + free(info_layout_portrait); + if (info_layout_landscape != NULL) + free(info_layout_landscape); +} + +void gridbox_set_item_deleted_cb(Evas_Object *gridbox, + void(*deleted_cb)(void *data, Evas_Object *obj)) { + retif(gridbox == NULL, , "invalid parameter"); + retif(deleted_cb == NULL, , "invalid parameter"); + + evas_object_data_set(gridbox, E_DATA_CB_DELETE_ITEM, deleted_cb); +} + +static void _gridbox_call_item_deleted_cb(Evas_Object *gridbox, void *data, + Evas_Object *obj) { + retif(gridbox == NULL, , "invalid parameter"); + + void (*deleted_cb)(void *data, Evas_Object *obj) = NULL; + + deleted_cb = evas_object_data_get(gridbox, E_DATA_CB_DELETE_ITEM); + + if (deleted_cb != NULL) { + deleted_cb(data, obj); + } +} + +void gridbox_add_item(Evas_Object *gridbox, Evas_Object *item, int is_prepend) { + const char *signal = NULL; + + retif(gridbox == NULL, , "invalid parameter"); + retif(item == NULL, , "invalid parameter"); + + struct appdata *ad = evas_object_data_get(gridbox, E_DATA_APP_DATA); + + if (ad != NULL) { + if (ad->angle == 270 || ad->angle == 90) { + signal = "box.landscape"; + } else { + signal = "box.portrait"; + } + } + + DBG("set to %s, %x", signal, item); + + elm_object_signal_emit(item, signal, "box.prog"); + edje_object_message_signal_process(_EDJ(item)); + elm_layout_sizing_eval(item); + + if (is_prepend == GRIDBOX_PREPEND) + elm_box_pack_start(gridbox, item); + else + elm_box_pack_end(gridbox, item); +} + +static void _gridbox_remove_item_anim_cb(void *data, Elm_Transit *transit) { + DBG(""); + retif(data == NULL, , "invalid parameter"); + retif(transit == NULL, , "invalid parameter"); + + gridbox_info_animation *info_animation = data; + + retif(info_animation->gridbox == NULL, , "invalid parameter"); + retif(info_animation->item == NULL, , "invalid parameter"); + + DBG("remove:%p", info_animation->item); + + elm_box_unpack(info_animation->gridbox, info_animation->item); + + _gridbox_call_item_deleted_cb(info_animation->gridbox, + noti_box_node_get(info_animation->item), info_animation->item); + noti_box_remove(info_animation->item); + + if (info_animation->update_cb != NULL) { + retif(info_animation->container == NULL, , "invalid parameter"); + retif(info_animation->noti == NULL, , "invalid parameter"); + + info_animation->update_cb(info_animation->container, + info_animation->noti, info_animation->pos); + } + + free(info_animation); + info_animation = NULL; +} + +void gridbox_remove_item(Evas_Object *gridbox, Evas_Object *item, int with_animation) { + DBG("remove:%p", item); + retif(gridbox == NULL, , "invalid parameter"); + retif(item == NULL, , "invalid parameter"); + + if (noti_box_get_status(item) == STATE_DELETING) { + return ; + } + noti_box_set_status(item, STATE_DELETING); + + if (with_animation == 1) { + gridbox_info_animation *info_animation = (gridbox_info_animation *) malloc( + sizeof(gridbox_info_animation)); + if (info_animation == NULL) + return; + info_animation->gridbox = gridbox; + info_animation->item = item; + info_animation->update_cb = NULL; + info_animation->container = NULL; + info_animation->noti = NULL; + info_animation->pos = 0; + + Elm_Transit *transit = elm_transit_add(); + //Fade in and out with layout object. + elm_transit_object_add(transit, item); + elm_transit_effect_fade_add(transit); + elm_transit_duration_set(transit, 0.7); + elm_transit_del_cb_set(transit, _gridbox_remove_item_anim_cb, + info_animation); + elm_transit_go(transit); + } else { + _gridbox_call_item_deleted_cb(gridbox, + noti_box_node_get(item), item); + elm_box_unpack(gridbox, item); + noti_box_remove(item); + } +} + +void gridbox_remove_all_item(Evas_Object *gridbox, int with_animation) { + DBG(""); + retif(gridbox == NULL, , "invalid parameter"); + + Eina_List *l; + Eina_List *l_next; + Evas_Object *obj; + Eina_List *item_list = elm_box_children_get(gridbox); + + EINA_LIST_FOREACH_SAFE(item_list, l, l_next, obj) + { + if (obj != NULL) { + // call deleted callback + gridbox_remove_item(gridbox, obj, with_animation); + } + } +} + +void gridbox_update_item(Evas_Object *gridbox, Evas_Object *item) { + + retif(gridbox == NULL, , "invalid parameter"); + retif(item == NULL, , "invalid parameter"); +} + +void gridbox_remove_and_add_item(Evas_Object *gridbox, Evas_Object *item + ,void (*update_cb)(Evas_Object *list, void *data, int is_prepend) + ,void *container, void *data, int pos) { + + retif(gridbox == NULL, , "invalid parameter"); + retif(item == NULL, , "invalid parameter"); + retif(update_cb == NULL, , "invalid parameter"); + retif(container == NULL, , "invalid parameter"); + retif(data == NULL, , "invalid parameter"); + + if (noti_box_get_status(item) == STATE_DELETING) { + return ; + } + noti_box_set_status(item, STATE_DELETING); + + gridbox_info_animation *info_animation = (gridbox_info_animation *) malloc( + sizeof(gridbox_info_animation)); + if (info_animation == NULL) + return; + info_animation->gridbox = gridbox; + info_animation->item = item; + info_animation->update_cb = update_cb; + info_animation->container = container; + info_animation->noti = data; + info_animation->pos = pos; + + Elm_Transit *transit = elm_transit_add(); + //Fade in and out with layout object. + elm_transit_object_add(transit, item); + elm_transit_effect_fade_add(transit); + elm_transit_duration_set(transit, 0.4); + elm_transit_del_cb_set(transit, _gridbox_remove_item_anim_cb, + info_animation); + elm_transit_go(transit); +} + +void gridbox_finalize_rotation_cb(void *data) { + retif(data == NULL, , "invalid parameter"); + Evas_Object *gridbox = data; + + elm_box_recalculate(gridbox); +} + +void gridbox_rotation(Evas_Object *gridbox, int angle) { + const char *signal = NULL; + + retif(gridbox == NULL, , "invalid parameter"); + + gridbox_info_layout *info_layout_portrait = evas_object_data_get(gridbox, + E_DATA_LAYOUT_PORTRAIT); + gridbox_info_layout *info_layout_landscape = evas_object_data_get(gridbox, + E_DATA_LAYOUT_LANDSCAPE); + + retif(info_layout_portrait == NULL || info_layout_landscape == NULL, , + "gridbox is crashed"); + + Eina_List *l; + Eina_List *l_next; + Evas_Object *obj; + Eina_List *item_list = elm_box_children_get(gridbox); + + if (angle == 270 || angle == 90) { + signal = "box.landscape"; + } else { + signal = "box.portrait"; + } + + DBG("all count:%d", eina_list_count (item_list)); + + EINA_LIST_FOREACH_SAFE(item_list, l, l_next, obj) + { + if (obj != NULL) { + elm_object_signal_emit(obj, signal, "box.prog"); + edje_object_message_signal_process(_EDJ(obj)); + elm_layout_sizing_eval(obj); + DBG("set to %s, %x", signal, obj); + } + } + + if (angle == 270 || angle == 90) { + elm_box_layout_set(gridbox, _gridbox_layout, info_layout_landscape, + NULL); + +#if 0 + layout_data = elm_box_transition_new(0.0, _gridbox_layout, + info_layout_portrait, NULL, _gridbox_layout, + info_layout_landscape, NULL, gridbox_finalize_rotation_cb, + gridbox); +#endif + } else { + elm_box_layout_set(gridbox, _gridbox_layout, info_layout_portrait, + NULL); +#if 0 + layout_data = elm_box_transition_new(0.0, _gridbox_layout, + info_layout_landscape, NULL, _gridbox_layout, + info_layout_portrait, NULL, gridbox_finalize_rotation_cb, + gridbox); +#endif + } + +#if 0 + elm_box_layout_set(gridbox, elm_box_layout_transition, layout_data, + elm_box_transition_free); +#endif + DBG("Angle Rotation is %d", angle); +} diff --git a/daemon/notifications/noti_gridbox.h b/daemon/notifications/noti_gridbox.h new file mode 100755 index 0000000..03b2eb4 --- /dev/null +++ b/daemon/notifications/noti_gridbox.h @@ -0,0 +1,34 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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. + */ + +#ifndef __QUICKPANEL_GRIDBOX_H__ +#define __QUICKPANEL_GRIDBOX_H__ + +#define GRIDBOX_PREPEND 1 +#define GRIDBOX_APPEND 0 + +Evas_Object *gridbox_create(Evas_Object *parent, void *data); +void gridbox_remove(Evas_Object *gridbox); +void gridbox_add_item(Evas_Object *gridbox, Evas_Object *item, int is_prepend); +void gridbox_remove_item(Evas_Object *gridbox, Evas_Object *item, int with_animation); +void gridbox_rotation(Evas_Object *gridbox, int angle); +void gridbox_remove_and_add_item(Evas_Object *gridbox, Evas_Object *item + ,void (*update_cb)(Evas_Object *list, void *data, int is_prepend) + ,void *container, void *data, int pos); +void gridbox_remove_all_item(Evas_Object *gridbox, int with_animation); +void gridbox_set_item_deleted_cb(Evas_Object *gridbox, + void(*deleted_cb)(void *data, Evas_Object *obj)); +#endif diff --git a/daemon/notifications/noti_node.c b/daemon/notifications/noti_node.c new file mode 100755 index 0000000..440af1b --- /dev/null +++ b/daemon/notifications/noti_node.c @@ -0,0 +1,146 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 "quickpanel-ui.h" +#include "common.h" +#include "list_util.h" +#include "noti_node.h" + +static void _noti_node_free(noti_node_item *node); + +void noti_node_create(noti_node **handle) +{ + retif(handle == NULL, , "Invalid parameter!"); + + *handle = (noti_node *)malloc(sizeof(noti_node)); + + if (*handle != NULL) { + (*handle)->table = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, + (GDestroyNotify)_noti_node_free); + + (*handle)->n_ongoing = 0; + (*handle)->n_noti = 0; + } else { + *handle = NULL; + } +} + +void noti_node_destroy(noti_node **handle) +{ + retif(handle == NULL, , "Invalid parameter!"); + retif(*handle == NULL, , "Invalid parameter!"); + + g_hash_table_remove_all((*handle)->table); + g_hash_table_destroy((*handle)->table); + (*handle)->table = NULL; + + free((*handle)); + *handle = NULL; +} + +noti_node_item *noti_node_add(noti_node *handle, notification_h noti, void *view) +{ + int priv_id = 0; + notification_type_e noti_type = NOTIFICATION_TYPE_NONE; + noti_node_item *node = NULL; + + retif(handle == NULL || noti == NULL, NULL, "Invalid parameter!"); + + if (notification_get_id(noti, NULL, &priv_id) == NOTIFICATION_ERROR_NONE) { + node = malloc(sizeof(noti_node_item)); + if (!node) { + ERR("fail to alloc item"); + return NULL; + } + + node->noti = noti; + node->view = view; + + g_hash_table_insert(handle->table, GINT_TO_POINTER(priv_id), (gpointer *)node); + + notification_get_type(noti, ¬i_type); + + if (noti_type == NOTIFICATION_TYPE_NOTI) + handle->n_noti++; + else if (noti_type == NOTIFICATION_TYPE_ONGOING) + handle->n_ongoing++; + + return node; + } + + return NULL; +} + +void noti_node_remove(noti_node *handle, int priv_id) +{ + notification_type_e noti_type = NOTIFICATION_TYPE_NONE; + + retif(handle == NULL, , "Invalid parameter!"); + retif(handle->table == NULL, , "Invalid parameter!"); + + noti_node_item *item = noti_node_get(handle, priv_id); + + if (item != NULL) { + if (item->noti != NULL) { + notification_get_type(item->noti, ¬i_type); + + if (noti_type == NOTIFICATION_TYPE_NOTI) + handle->n_noti--; + else if (noti_type == NOTIFICATION_TYPE_ONGOING) + handle->n_ongoing--; + } + + notification_free(item->noti); + item->noti = NULL; + item->view = NULL; + + if (g_hash_table_remove(handle->table, GINT_TO_POINTER(priv_id))) + { + INFO("success to remove %d", priv_id); + } + } +} + +noti_node_item *noti_node_get(noti_node *handle, int priv_id) +{ + retif(handle == NULL, NULL, "Invalid parameter!"); + retif(handle->table == NULL, NULL, "Invalid parameter!"); + + return (noti_node_item *)g_hash_table_lookup + (handle->table, GINT_TO_POINTER(priv_id)); +} + +int noti_node_get_item_count(noti_node *handle, notification_type_e noti_type) +{ + retif(handle == NULL, 0, "Invalid parameter!"); + + if (noti_type == NOTIFICATION_TYPE_NOTI) + return handle->n_noti; + else if (noti_type == NOTIFICATION_TYPE_ONGOING) + return handle->n_ongoing; + + return 0; +} + +static void _noti_node_free(noti_node_item *node) +{ + retif(node == NULL, , "Invalid parameter!"); + + DBG("item_node is freed:%p", node); + + free(node); +} diff --git a/daemon/notifications/noti_node.h b/daemon/notifications/noti_node.h new file mode 100755 index 0000000..00debbc --- /dev/null +++ b/daemon/notifications/noti_node.h @@ -0,0 +1,41 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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. + */ + +#ifndef __QUICKPANEL_NOTI_NODE_H__ +#define __QUICKPANEL_NOTI_NODE_H__ + +#include <glib.h> +#include <notification.h> + +typedef struct _noti_node { + GHashTable *table; + int n_ongoing; + int n_noti; +} noti_node; + +typedef struct _noti_node_item { + notification_h noti; + void *view; +} noti_node_item; + +void noti_node_create(noti_node **handle); +void noti_node_destroy(noti_node **handle); +noti_node_item *noti_node_add(noti_node *handle, notification_h noti, void *view); +void noti_node_remove(noti_node *handle, int priv_id); +noti_node_item *noti_node_get(noti_node *handle, int priv_id); +int noti_node_get_item_count(noti_node *handle, notification_type_e noti_type); + +#endif diff --git a/daemon/notifications/noti_win.c b/daemon/notifications/noti_win.c new file mode 100755 index 0000000..fa8330f --- /dev/null +++ b/daemon/notifications/noti_win.c @@ -0,0 +1,314 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <utilX.h> + +#define NOTI_HEIGHT 50 +#ifndef __UNUSED__ +#define __UNUSED__ __attribute__((unused)) +#endif +/* Using this macro to emphasize that some portion like stacking and +rotation handling are implemented for X based platform +*/ + +#ifdef HAVE_X +#include <Ecore_X.h> +#endif +#include "common.h" +#include "noti_win.h" + +struct Internal_Data { + Evas_Object *content; + Ecore_Event_Handler *rotation_event_handler; + Evas_Coord w; + Evas_Coord h; + int angle; + enum Noti_Orient orient; +}; + +static const char *data_key = "_data"; + +static void _set_win_type_notification_level(Evas_Object *win) +{ + retif(win == NULL, , "invalid parameter"); + + Ecore_X_Window w = elm_win_xwindow_get(win); + + if (w > 0) { + ecore_x_icccm_hints_set(w, 0, ECORE_X_WINDOW_STATE_HINT_NONE, 0, 0, + 0, 0, 0); + ecore_x_netwm_opacity_set(w, 0); + + ecore_x_netwm_window_type_set(w, + ECORE_X_WINDOW_TYPE_NOTIFICATION); + utilx_set_system_notification_level(ecore_x_display_get(), w, + UTILX_NOTIFICATION_LEVEL_HIGH); + } +} + +static void _show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) +{ + struct Internal_Data *wd = evas_object_data_get(obj, data_key); + + if (!wd) + return; + if (wd->content) + evas_object_show(wd->content); +} + +static void _content_hide(void *data, Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + evas_object_hide(data); +} + +static void _content_changed_size_hints(void *data, Evas *e __UNUSED__, + Evas_Object *obj, void *event_info __UNUSED__) +{ + Evas_Coord h; + struct Internal_Data *wd = evas_object_data_get(data, data_key); + + if (!wd) + return; + + evas_object_size_hint_min_get(obj, NULL, &h); + if ((h > 0)) { + wd->h = h; + evas_object_size_hint_min_set(obj, wd->w, wd->h); + evas_object_size_hint_min_set(data, wd->w, wd->h); + evas_object_resize(data, wd->w, wd->h); + } +} + +static void _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info) +{ + struct Internal_Data *wd = evas_object_data_get(obj, data_key); + Evas_Object *sub = event_info; + + if (!wd) + return; + if (sub == wd->content) { + evas_object_event_callback_del(wd->content, EVAS_CALLBACK_HIDE, + _content_hide); + evas_object_event_callback_del(wd->content, + EVAS_CALLBACK_CHANGED_SIZE_HINTS, + _content_changed_size_hints); + wd->content = NULL; + } +} + +static void _del(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, + void *event_info __UNUSED__) +{ + struct Internal_Data *wd = evas_object_data_get(obj, data_key); + + if (!wd) + return; + if (wd->rotation_event_handler) + ecore_event_handler_del(wd->rotation_event_handler); + evas_object_data_set(data, data_key, NULL); + free(wd); +} + +#ifdef HAVE_X +static void _update_geometry_on_rotation(Evas_Object *obj, int angle, + int *x, int *y, int *w) +{ + Evas_Coord root_w, root_h; + struct Internal_Data *wd = evas_object_data_get(obj, data_key); + + if (!wd) + return; + + ecore_x_window_size_get(ecore_x_window_root_first_get(), &root_w, + &root_h); + + /* rotate window */ + switch (angle) { + case 90: + *w = root_h; + if (wd->orient == NOTI_ORIENT_BOTTOM) + *x = root_w - wd->h; + break; + case 270: + *w = root_h; + if (!(wd->orient == NOTI_ORIENT_BOTTOM)) + *x = root_w - wd->h; + break; + case 180: + *w = root_w; + if (!wd->orient == NOTI_ORIENT_BOTTOM) + *y = root_h - wd->h; + break; + case 0: + default: + *w = root_w; + if (wd->orient == NOTI_ORIENT_BOTTOM) + *y = root_h - wd->h; + break; + } +} + +static void _win_rotated(Evas_Object *obj) +{ + int x = 0; + int y = 0; + int w = 0; + int angle = 0; + struct Internal_Data *wd = evas_object_data_get(obj, data_key); + + if (!wd) + return; + angle = elm_win_rotation_get(obj); + if (angle % 90) + return; + angle %= 360; + if (angle < 0) + angle += 360; + wd->angle = angle; + + _update_geometry_on_rotation(obj, wd->angle, &x, &y, &w); + + evas_object_move(obj, x, y); + wd->w = w; + evas_object_resize(obj, wd->w, wd->h); +} + +static Eina_Bool _prop_change(void *data, int type __UNUSED__, void *event) +{ + Ecore_X_Event_Window_Property *ev; + struct Internal_Data *wd = evas_object_data_get(data, data_key); + + if (!wd) + return ECORE_CALLBACK_PASS_ON; + ev = event; + if (ev->atom == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) + if (ev->win == elm_win_xwindow_get(data)) + _win_rotated(data); + return ECORE_CALLBACK_PASS_ON; +} +#endif + +Evas_Object *noti_win_add(Evas_Object *parent) +{ + Evas_Object *win; + Evas_Object *bg; + struct Internal_Data *wd; + Evas_Coord w = 0; + + win = elm_win_add(parent, "noti_win", ELM_WIN_NOTIFICATION); + elm_win_alpha_set(win, EINA_TRUE); + + if (!win) + return NULL; + elm_win_title_set(win, "noti_win"); + elm_win_borderless_set(win, EINA_TRUE); + elm_win_autodel_set(win, EINA_TRUE); + evas_object_size_hint_weight_set(win, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(win, EVAS_HINT_FILL, EVAS_HINT_FILL); + bg = elm_bg_add(win); + evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, bg); + evas_object_show(bg); + + _set_win_type_notification_level(win); + + wd = (struct Internal_Data *) calloc(1, sizeof(struct Internal_Data)); + if (!wd) + return NULL; + evas_object_data_set(win, data_key, wd); + wd->angle = 0; + wd->orient = NOTI_ORIENT_TOP; + evas_object_move(win, 0, 0); +#ifdef HAVE_X + ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, NULL); + evas_object_resize(win, w, NOTI_HEIGHT); + wd->rotation_event_handler = ecore_event_handler_add( + ECORE_X_EVENT_WINDOW_PROPERTY, _prop_change, win); +#endif + wd->w = w; + wd->h = NOTI_HEIGHT; + evas_object_smart_callback_add(win, "sub-object-del", _sub_del, NULL); + evas_object_event_callback_add(win, EVAS_CALLBACK_SHOW, _show, NULL); + evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _del, NULL); + return win; +} + +void noti_win_content_set(Evas_Object *obj, Evas_Object *content) +{ + Evas_Coord h; + struct Internal_Data *wd; + + if (!obj) + return; + wd = evas_object_data_get(obj, data_key); + if (!wd) + return; + if (wd->content) + evas_object_del(content); + wd->content = content; + if (content) { + evas_object_size_hint_weight_set(wd->content, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + elm_win_resize_object_add(obj, wd->content); + evas_object_size_hint_min_get(wd->content, NULL, &h); + if (h) + wd->h = h; + evas_object_size_hint_min_set(wd->content, wd->w, wd->h); + evas_object_resize(obj, wd->w, wd->h); + evas_object_event_callback_add(wd->content, EVAS_CALLBACK_HIDE, + _content_hide, obj); + evas_object_event_callback_add(wd->content, + EVAS_CALLBACK_CHANGED_SIZE_HINTS, + _content_changed_size_hints, obj); + } +} + +void noti_win_orient_set(Evas_Object *obj, enum Noti_Orient orient) +{ +#ifdef HAVE_X + Evas_Coord root_w, root_h; +#endif + struct Internal_Data *wd = evas_object_data_get(obj, data_key); + + if (!wd) + return; + if (orient >= NOTI_ORIENT_LAST) + return; +#ifdef HAVE_X + ecore_x_window_size_get(ecore_x_window_root_first_get(), &root_w, + &root_h); +#endif + switch (orient) { + case NOTI_ORIENT_BOTTOM: +#ifdef HAVE_X + evas_object_move(obj, 0, root_h - wd->h); +#endif + wd->orient = NOTI_ORIENT_BOTTOM; + break; + case NOTI_ORIENT_TOP: + default: +#ifdef HAVE_X + evas_object_move(obj, 0, 0); +#endif + wd->orient = NOTI_ORIENT_TOP; + break; + } +} diff --git a/daemon/notifications/noti_win.h b/daemon/notifications/noti_win.h new file mode 100755 index 0000000..951ac06 --- /dev/null +++ b/daemon/notifications/noti_win.h @@ -0,0 +1,41 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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. + */ + +#ifndef __NOTI_WIN_H__ +#define __NOTI_WIN_H__ +#include <Evas.h> + +enum Noti_Orient { + NOTI_ORIENT_TOP = 0, + NOTI_ORIENT_BOTTOM, + NOTI_ORIENT_LAST + } ; + +/* Creates and return a new window (of widget type elm_win) of width equal to +root window +*/ +Evas_Object *noti_win_add(Evas_Object *parent); + +/* Sets an Evas Object as content of the notification window created using +noti_win_add +*/ +void noti_win_content_set(Evas_Object *obj, Evas_Object *content); + +/* Sets the orientation of the notification window, this can be of type +Noti_Orient +*/ +void noti_win_orient_set(Evas_Object *obj, enum Noti_Orient orient); +#endif diff --git a/daemon/notifications/status_msg.c b/daemon/notifications/status_msg.c new file mode 100755 index 0000000..898d7e4 --- /dev/null +++ b/daemon/notifications/status_msg.c @@ -0,0 +1,315 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <Ecore_X.h> +#include <vconf.h> +#include <notification.h> + +#include "quickpanel-ui.h" +#include "common.h" +#include "noti_win.h" + +#define QP_STATUS_DURATION 3 +#define QP_STATUS_DETAIL_DURATION 6 + +#define STATUS_MSG_LEN 1024 +#define DEFAULT_ICON ICONDIR "/quickpanel_icon_default.png" + +#define E_DATA_STATUS_DETAIL "detail" + +static Evas_Object *g_status_win; +static Ecore_Timer *g_status_timer; +static int g_noti_height; + +static int quickpanel_status_init(void *data); +static int quickpanel_status_fini(void *data); +static void quickpanel_status_reflesh(void *data); + +QP_Module ticker_status = { + .name = "ticker_status", + .init = quickpanel_status_init, + .fini = quickpanel_status_fini, + .hib_enter = NULL, + .hib_leave = NULL, + .lang_changed = NULL, + .refresh = quickpanel_status_reflesh +}; + +/***************************************************************************** + * + * (Static) Util functions + * + *****************************************************************************/ +static void _quickpanel_status_hide(void *data) +{ + if (g_status_win) { + evas_object_hide(g_status_win); + evas_object_del(g_status_win); + g_status_win = NULL; + } +} + +static void _quickpanel_status_set_text(Evas_Object *detail, const char *message) { + retif(detail == NULL, , "Invalid parameter!"); + retif(message == NULL, , "Invalid parameter!"); + + elm_object_part_text_set(detail, "elm.text", message); +} + +static Eina_Bool _quickpanel_status_timeout_cb(void *data) +{ + DBG(""); + + g_status_timer = NULL; + + _quickpanel_status_hide(data); + + return ECORE_CALLBACK_CANCEL; +} + +static void _quickpanel_status_detail_hide_cb(void *data, Evas *e, + Evas_Object *obj, + void *event_info) +{ + if (g_status_timer) { + ecore_timer_del(g_status_timer); + g_status_timer = NULL; + } +} + +static void _quickpanel_status_detail_show_cb(void *data, Evas *e, + Evas_Object *obj, + void *event_info) +{ + DBG(""); +} + +static void _quickpanel_status_clicked_cb(void *data, Evas_Object *obj, + void *event_info) +{ + _quickpanel_status_hide(data); +} + +static void _noti_hide_cb(void *data, Evas_Object *obj, + const char *emission, const char *source) +{ + DBG(""); + + if (g_status_timer) { + ecore_timer_del(g_status_timer); + g_status_timer = NULL; + } +} + +static Evas_Object *_quickpanel_status_create_status_noti(const char *message, void *data) +{ + Evas_Object *status_noti = NULL; + Evas_Object *detail = NULL; + const char *data_win_height = NULL; + int noti_height = 0; + + retif(message == NULL, NULL, "Invalid parameter!"); + + status_noti = noti_win_add(NULL); + retif(status_noti == NULL, NULL, "Failed to add elm status_noti."); + + detail = elm_layout_add(status_noti); + if (!detail) { + ERR("Failed to get detailview."); + evas_object_del(status_noti); + return NULL; + } + elm_layout_theme_set(detail, "tickernoti", "base", "textonly"); + elm_object_signal_callback_add(detail, "request,hide", "", + _noti_hide_cb, NULL); + + data_win_height = (char *)elm_layout_data_get(detail, "height"); + if (data_win_height != NULL && elm_config_scale_get() > 0.0) + noti_height = (int)(elm_config_scale_get() + * atoi(data_win_height)); + evas_object_size_hint_min_set(detail, 1, noti_height); + g_noti_height = noti_height; + DBG("height:%d", g_noti_height); + + noti_win_content_set(status_noti, detail); + + _quickpanel_status_set_text(detail, message); + /* Use style "default" for detailview mode and + * "info" for text only mode + */ + elm_object_style_set(status_noti, "textonly"); + evas_object_data_set(status_noti, E_DATA_STATUS_DETAIL, detail); + + return status_noti; +} + +static int _quickpanel_status_get_angle(void *data) +{ + struct appdata *ad = (struct appdata *)data; + Ecore_X_Window xwin, root; + int ret = 0, angle = 0, count = 0; + unsigned char *prop_data = NULL; + + xwin = elm_win_xwindow_get(ad->win); + root = ecore_x_window_root_get(xwin); + + ret = ecore_x_window_prop_property_get(root, + ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE, + ECORE_X_ATOM_CARDINAL, 32, + &prop_data, &count); + + if (ret && prop_data) { + memcpy(&angle, prop_data, sizeof(int)); + + if (prop_data) + free(prop_data); + + return angle; + } else { + ERR("Fail to get angle"); + if (prop_data) + free(prop_data); + + return -1; + } +} + +static void _quickpanel_status_update_geometry_on_rotation(void *data, int *x, int *y, int *w, int *h) { + int angle = 0; + + if (!data) + return; + + angle = _quickpanel_status_get_angle(data); + Evas_Coord root_w, root_h; + + /* + * manually calculate win_status_noti_indi window position & size + * - win_indi is not full size window + */ + ecore_x_window_size_get(ecore_x_window_root_first_get(), &root_w, &root_h); + + // rotate win + switch(angle) + { + case 90: + *w = g_noti_height; + *h = root_h; + break; + case 270: + *w = g_noti_height; + *h = root_h; + *x = root_w - g_noti_height; + break; + case 180: + *w = root_w; + *h = g_noti_height; + *y = root_h - g_noti_height; + break; + case 0: + default: + *w = root_w; + *h = g_noti_height; + break; + } + elm_win_rotation_set(g_status_win, angle); +} + +static void _quickpanel_status_win_rotated(void *data) { + retif(data == NULL, ,"data is NULL"); + + struct appdata *ad = data; + int x = 0, y = 0, w = 0, h = 0; + + _quickpanel_status_update_geometry_on_rotation(ad, &x, &y, &w, &h); + + if (g_status_win != NULL) { + evas_object_move(g_status_win, x, y); + evas_object_resize(g_status_win, w, h); + } +} + +static void _quickpanel_status_cb(const char *message, void *data) +{ + DBG(""); + retif(message == NULL, ,"message is NULL"); + retif(data == NULL, ,"data is NULL"); + + if (g_status_timer) + ecore_timer_del(g_status_timer); + + /* Skip if previous status is still shown */ + if (g_status_win != NULL) { + Evas_Object *detail = evas_object_data_get(g_status_win, E_DATA_STATUS_DETAIL); + _quickpanel_status_set_text(detail, message); + elm_win_activate(g_status_win); + } else { + g_status_win = _quickpanel_status_create_status_noti(message, data); + if (g_status_win == NULL) { + ERR("Fail to create status_noti"); + return; + } + + _quickpanel_status_win_rotated(data); + evas_object_show(g_status_win); + + evas_object_event_callback_add(g_status_win, EVAS_CALLBACK_SHOW, + _quickpanel_status_detail_show_cb, + g_status_win); + evas_object_event_callback_add(g_status_win, EVAS_CALLBACK_HIDE, + _quickpanel_status_detail_hide_cb, + g_status_win); + evas_object_smart_callback_add(g_status_win, "clicked", + _quickpanel_status_clicked_cb, + g_status_win); + } + + g_status_timer = ecore_timer_add(QP_STATUS_DURATION, + _quickpanel_status_timeout_cb, NULL); +} + +/***************************************************************************** + * + * Util functions + * + *****************************************************************************/ +static int quickpanel_status_init(void *data) +{ + int ret = QP_OK; + + ret = notification_status_monitor_message_cb_set(_quickpanel_status_cb, data); + + return ret; +} + +static int quickpanel_status_fini(void *data) +{ + int ret = 0; + _quickpanel_status_hide(NULL); + + ret = notification_status_monitor_message_cb_unset(); + + return ret; +} + +static void quickpanel_status_reflesh(void *data) +{ + retif(data == NULL, , "Invalid parameter!"); + + if (g_status_win != NULL) { + _quickpanel_status_win_rotated(data); + } +} diff --git a/daemon/notifications/ticker.c b/daemon/notifications/ticker.c new file mode 100755 index 0000000..60952df --- /dev/null +++ b/daemon/notifications/ticker.c @@ -0,0 +1,726 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <Ecore_X.h> +#include <appcore-common.h> +#include <vconf.h> +#include <appsvc.h> +#include <app_service.h> +#include <notification.h> +#include <time.h> +#include <feedback.h> + +#include "quickpanel-ui.h" +#include "common.h" +#include "noti_win.h" + +#define QP_TICKER_DURATION 5 +#define QP_TICKER_DETAIL_DURATION 6 + +#define TICKER_MSG_LEN 1024 +#define DEFAULT_ICON ICONDIR "/quickpanel_icon_default.png" + +static Evas_Object *g_window; +static Evas_Object *g_ticker; +static Ecore_Timer *g_timer; +static int g_noti_height; + +static int quickpanel_ticker_init(void *data); +static int quickpanel_ticker_fini(void *data); +static int quickpanel_ticker_enter_hib(void *data); +static int quickpanel_ticker_leave_hib(void *data); +static void quickpanel_ticker_reflesh(void *data); + +QP_Module ticker = { + .name = "ticker", + .init = quickpanel_ticker_init, + .fini = quickpanel_ticker_fini, + .hib_enter = quickpanel_ticker_enter_hib, + .hib_leave = quickpanel_ticker_leave_hib, + .lang_changed = NULL, + .refresh = quickpanel_ticker_reflesh +}; + +static int latest_inserted_time; + +/***************************************************************************** + * + * (Static) Util functions + * + *****************************************************************************/ + +static int _quickpanel_ticker_check_ticker_off(notification_h noti) +{ + char *pkgname = NULL; + int ret = 0; + int boolval = 0; + + notification_get_application(noti, &pkgname); + + if (pkgname == NULL) + notification_get_pkgname(noti, &pkgname); + + if (pkgname == NULL) + return 1; /* Ticker is not displaying. */ + + if (!strcmp(pkgname, VENDOR".message")) { + ret = vconf_get_bool( + VCONFKEY_SETAPPL_STATE_TICKER_NOTI_MESSAGES_BOOL, + &boolval); + if (ret == 0 && boolval == 0) + return 1; + } else if (!strcmp(pkgname, VENDOR".email")) { + ret = vconf_get_bool( + VCONFKEY_SETAPPL_STATE_TICKER_NOTI_EMAIL_BOOL, + &boolval); + if (ret == 0 && boolval == 0) + return 1; + } else if (!strcmp(pkgname, VENDOR".ims-syspopup")) { + ret = vconf_get_bool( + VCONFKEY_SETAPPL_STATE_TICKER_NOTI_IM_BOOL, + &boolval); + if (ret == 0 && boolval == 0) + return 1; + } + + /* Displaying ticker! */ + return 0; +} + +static int _quickpanel_ticker_check_displaying_contents_off(notification_h noti) +{ + char *pkgname = NULL; + int ret = 0; + int boolval = 0; + + notification_get_application(noti, &pkgname); + + if (pkgname == NULL) + notification_get_pkgname(noti, &pkgname); + + if (pkgname == NULL) + return 0; /* Ticker is not displaying. */ + + if (!strcmp(pkgname, VENDOR".message")) { + ret = vconf_get_bool( + VCONFKEY_TICKER_NOTI_DISPLAY_CONTENT_MESSASGES, + &boolval); + if (ret == 0 && boolval == 0) + return 1; + } else if (!strcmp(pkgname, VENDOR".email")) { + ret = vconf_get_bool( + VCONFKEY_TICKER_NOTI_DISPLAY_CONTENT_EMAIL, + &boolval); + if (ret == 0 && boolval == 0) + return 1; + } else if (!strcmp(pkgname, VENDOR".ims-syspopup")) { + ret = vconf_get_bool( + VCONFKEY_TICKER_NOTI_DISPLAY_CONTENT_IM, + &boolval); + if (ret == 0 && boolval == 0) + return 1; + } + + /* Displaying ticker! */ + return 0; +} + +static inline void __ticker_only_noti_del(notification_h noti) +{ + int applist = NOTIFICATION_DISPLAY_APP_ALL; + + retif(noti == NULL, ,"noti is null"); + + notification_get_display_applist(noti, &applist); + if (applist & NOTIFICATION_DISPLAY_APP_TICKER) { + if (!(applist & NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY)) { + char *pkgname = NULL; + int priv_id = 0; + + notification_get_pkgname(noti, &pkgname); + notification_get_id(noti, NULL, &priv_id); + notification_delete_by_priv_id(pkgname, + NOTIFICATION_TYPE_NONE, + priv_id); + } + } +} + +static void _quickpanel_ticker_hide(void *data) +{ + if (g_ticker) { + evas_object_hide(g_ticker); + evas_object_del(g_ticker); + g_ticker = NULL; + } +} + +static Eina_Bool _quickpanel_ticker_timeout_cb(void *data) +{ + DBG(""); + + g_timer = NULL; + + _quickpanel_ticker_hide(data); + + return ECORE_CALLBACK_CANCEL; +} + +static void _quickpanel_ticker_detail_hide_cb(void *data, Evas *e, + Evas_Object *obj, + void *event_info) +{ + DBG(""); + notification_h noti = (notification_h) data; + + if (g_timer) { + ecore_timer_del(g_timer); + g_timer = NULL; + } + + retif(noti == NULL, , "Invalid parameter!"); + + __ticker_only_noti_del(noti); + notification_free(noti); +} + +static void _quickpanel_ticker_detail_show_cb(void *data, Evas *e, + Evas_Object *obj, + void *event_info) +{ + DBG(""); +} + +static void _quickpanel_ticker_clicked_cb(void *data, Evas_Object *obj, + void *event_info) +{ + notification_h noti = (notification_h) data; + char *caller_pkgname = NULL; + char *pkgname = NULL; + bundle *args = NULL; + bundle *single_service_handle = NULL; + int priv_id = 0; + int flags = 0; + int ret = 0; + int val = 0; + int flag_launch = 0; + int flag_delete = 0; + int type = NOTIFICATION_TYPE_NONE; + + DBG(""); + + retif(noti == NULL, , "Invalid parameter!"); + + /* Check idle lock state */ + ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &val); + + /* If Lock state, there is not any action when clicked. */ + if (ret != 0 || val == VCONFKEY_IDLE_LOCK) + return; + + notification_get_pkgname(noti, &caller_pkgname); + notification_get_application(noti, &pkgname); + if (pkgname == NULL) + pkgname = caller_pkgname; + + notification_get_id(noti, NULL, &priv_id); + notification_get_property(noti, &flags); + notification_get_type(noti, &type); + + if (flags & NOTIFICATION_PROP_DISABLE_APP_LAUNCH) + flag_launch = 0; + else + flag_launch = 1; + + if (flags & NOTIFICATION_PROP_DISABLE_AUTO_DELETE) + flag_delete = 0; + else + flag_delete = 1; + + notification_get_execute_option(noti, + NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, + NULL, &single_service_handle); + + if (flag_launch == 1) { + if (single_service_handle != NULL) + appsvc_run_service(single_service_handle, 0, NULL, + NULL); + else { + notification_get_args(noti, &args, NULL); + quickpanel_launch_app(pkgname, args); + } + + /* Hide quickpanel */ + Ecore_X_Window zone; + zone = ecore_x_e_illume_zone_get(elm_win_xwindow_get(g_window)); + ecore_x_e_illume_quickpanel_state_send(zone, + ECORE_X_ILLUME_QUICKPANEL_STATE_OFF); + } + + if (flag_delete == 1 && type == NOTIFICATION_TYPE_NOTI) { + notification_delete_by_priv_id(caller_pkgname, + NOTIFICATION_TYPE_NOTI, + priv_id); + } +} + +static void _quickpanel_ticker_button_clicked_cb(void *data, Evas_Object *obj, + void *event_info) +{ + DBG(""); + + if (g_timer) { + ecore_timer_del(g_timer); + g_timer = NULL; + } + + _quickpanel_ticker_hide(data); +} + +static Evas_Object *_quickpanel_ticker_create_button(Evas_Object *parent, + notification_h noti) +{ + Evas_Object *button = NULL; + int ret = 0; + int val = 0; + + retif(noti == NULL || parent == NULL, NULL, "Invalid parameter!"); + + /* Check idle lock state */ + ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &val); + /* If Lock state, button is diabled */ + if (ret != 0 || val == VCONFKEY_IDLE_LOCK) + return NULL; + + button = elm_button_add(parent); + elm_object_style_set(button, "tickernoti"); + elm_object_text_set(button, _S("IDS_COM_BODY_CLOSE")); + evas_object_smart_callback_add(button, "clicked", + _quickpanel_ticker_button_clicked_cb, noti); + + return button; +} + +static Evas_Object *_quickpanel_ticker_create_icon(Evas_Object *parent, + notification_h noti) +{ + char *icon_path = NULL; + Evas_Object *icon = NULL; + + retif(noti == NULL || parent == NULL, NULL, "Invalid parameter!"); + + notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON, &icon_path); + icon = elm_image_add(parent); + + if (icon_path == NULL + || (elm_image_file_set(icon, icon_path, NULL) == EINA_FALSE)) { + elm_image_file_set(icon, DEFAULT_ICON, NULL); + elm_image_resizable_set(icon, EINA_TRUE, EINA_TRUE); + } + + return icon; +} + +static char *_quickpanel_ticker_get_label(notification_h noti) +{ + char buf[TICKER_MSG_LEN] = { 0, }; + int len = 0; + char *domain = NULL; + char *dir = NULL; + char *result_title = NULL; + char *result_content = NULL; + char *title_utf8 = NULL; + char *content_utf8 = NULL; + notification_error_e noti_err = NOTIFICATION_ERROR_NONE; + + retif(noti == NULL, NULL, "Invalid parameter!"); + + notification_get_text_domain(noti, &domain, &dir); + if (domain != NULL && dir != NULL) + bindtextdomain(domain, dir); + + noti_err = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE, + &result_title); + if (noti_err == NOTIFICATION_ERROR_NONE && result_title) + title_utf8 = elm_entry_utf8_to_markup(result_title); + + if (_quickpanel_ticker_check_displaying_contents_off(noti) == 1) { + noti_err = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT_FOR_DISPLAY_OPTION_IS_OFF, + &result_content); + } + else { + noti_err = notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT, + &result_content); + } + + if (noti_err == NOTIFICATION_ERROR_NONE && result_content) + content_utf8 = elm_entry_utf8_to_markup(result_content); + + if (title_utf8 && content_utf8) { + len = snprintf(buf, sizeof(buf), + "<font_size=26><color=#BABABA>%s</color></font>" + "<br><font_size=29><color=#F4F4F4>%s</color></font>", + title_utf8, content_utf8); + } else if (title_utf8) { + len = snprintf(buf, sizeof(buf), + "<font_size=29><color=#BABABA>%s</color></font>", + title_utf8); + } + + if (title_utf8) + free(title_utf8); + + if (content_utf8) + free(content_utf8); + + if (len > 0) + return strdup(buf); + + return NULL; +} + +static void _noti_hide_cb(void *data, Evas_Object *obj, + const char *emission, const char *source) +{ + DBG(""); + + if (g_timer) { + ecore_timer_del(g_timer); + g_timer = NULL; + } + + _quickpanel_ticker_hide(data); +} + +static Evas_Object *_quickpanel_ticker_create_tickernoti(void *data) +{ + notification_h noti = (notification_h) data; + Evas_Object *tickernoti = NULL; + Evas_Object *icon = NULL; + Evas_Object *detail = NULL; + Evas_Object *button = NULL; + char *buf = NULL; + const char *data_win_height = NULL; + int noti_height = 0; + + retif(noti == NULL, NULL, "Invalid parameter!"); + + tickernoti = noti_win_add(NULL); + retif(tickernoti == NULL, NULL, "Failed to add elm tickernoti."); + + detail = elm_layout_add(tickernoti); + if (!detail) { + ERR("Failed to get detailview."); + evas_object_del(tickernoti); + return NULL; + } + elm_layout_theme_set(detail, "tickernoti", "base", "default"); + elm_object_signal_callback_add(detail, "request,hide", "", + _noti_hide_cb, noti); + + data_win_height = (char *)elm_layout_data_get(detail, "height"); + if (data_win_height != NULL && elm_config_scale_get() > 0.0) + noti_height = (int)(elm_config_scale_get() + * atoi(data_win_height)); + evas_object_size_hint_min_set(detail, 1, noti_height); + g_noti_height = noti_height; + + noti_win_content_set(tickernoti, detail); + + icon = _quickpanel_ticker_create_icon(detail, noti); + if (icon != NULL) + elm_object_part_content_set(detail, "icon", icon); + + button = _quickpanel_ticker_create_button(detail, noti); + if (button != NULL) + elm_object_part_content_set(detail, "button", button); + + buf = _quickpanel_ticker_get_label(noti); + if (buf != NULL) { + elm_object_part_text_set(detail, "elm.text", buf); + free(buf); + } + + /* Use style "default" for detailview mode and + * "info" for text only mode + */ + elm_object_style_set(tickernoti, "default"); + + return tickernoti; +} + +static int _quickpanel_ticker_get_angle(void *data) +{ + struct appdata *ad = (struct appdata *)data; + Ecore_X_Window xwin, root; + int ret = 0, angle = 0, count = 0; + unsigned char *prop_data = NULL; + + xwin = elm_win_xwindow_get(ad->win); + root = ecore_x_window_root_get(xwin); + + ret = ecore_x_window_prop_property_get(root, + ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE, + ECORE_X_ATOM_CARDINAL, 32, + &prop_data, &count); + + if (ret && prop_data) { + memcpy(&angle, prop_data, sizeof(int)); + + if (prop_data) + free(prop_data); + + return angle; + } else { + ERR("Fail to get angle"); + if (prop_data) + free(prop_data); + + return -1; + } +} + +static void _quickpanel_ticker_update_geometry_on_rotation(void *data, int *x, int *y, int *w, int *h) { + int angle = 0; + + if (!data) + return; + angle = _quickpanel_ticker_get_angle(data); + Evas_Coord root_w, root_h; + + /* + * manually calculate win_tickernoti_indi window position & size + * - win_indi is not full size window + */ + ecore_x_window_size_get(ecore_x_window_root_first_get(), &root_w, &root_h); + + // rotate win + switch(angle) + { + case 90: + *w = g_noti_height; + *h = root_h; + break; + case 270: + *w = g_noti_height; + *h = root_h; + *x = root_w - g_noti_height; + break; + case 180: + *w = root_w; + *h = g_noti_height; + *y = root_h - g_noti_height; + break; + case 0: + default: + *w = root_w; + *h = g_noti_height; + break; + } + elm_win_rotation_set(g_ticker, angle); +} + +static void _quickpanel_ticker_win_rotated(void *data) { + retif(data == NULL, ,"data is NULL"); + struct appdata *ad = data; + int x = 0, y = 0, w = 0, h = 0; + + _quickpanel_ticker_update_geometry_on_rotation(ad, &x, &y, &w, &h); + + if (g_ticker != NULL) { + evas_object_move(g_ticker, x, y); + evas_object_resize(g_ticker, w, h); + } +} + +static void _quickpanel_ticker_noti_detailed_changed_cb(void *data, notification_type_e type, notification_op *op_list, int num_op) +{ + notification_h noti = NULL; + int flags = 0; + int applist = NOTIFICATION_DISPLAY_APP_ALL; + int ret = 0; + int op_type = 0; + int priv_id = 0; + + INFO("_quickpanel_ticker_noti_changed_cb"); + + retif(op_list == NULL, ,"op_list is NULL"); + + if (num_op == 1) { + notification_op_get_data(op_list, NOTIFICATION_OP_DATA_TYPE, &op_type); + notification_op_get_data(op_list, NOTIFICATION_OP_DATA_PRIV_ID, &priv_id); + DBG("op_type:%d", op_type); + DBG("op_priv_id:%d", priv_id); + + if (op_type == NOTIFICATION_OP_INSERT) { + noti = notification_load(NULL, priv_id); + } else if (op_type == NOTIFICATION_OP_UPDATE) { + noti = notification_load(NULL, priv_id); + } else { + return ; + } + } else { + return ; + } + + retif(noti == NULL, ,"noti is NULL"); + + notification_get_display_applist(noti, &applist); + if (!(applist & NOTIFICATION_DISPLAY_APP_TICKER)) { + DBG("No Ticker Msg"); + notification_free(noti); + return ; + } + + /* Check setting's event notification */ + ret = _quickpanel_ticker_check_ticker_off(noti); + if (ret == 1) { + INFO("Disable tickernoti ret : %d", ret); + /* delete temporary here only ticker noti display item */ + __ticker_only_noti_del(noti); + notification_free(noti); + + return; + } + + /* Play sound */ + notification_sound_type_e nsound_type = NOTIFICATION_SOUND_TYPE_NONE; + const char *nsound_path = NULL; + + notification_get_sound(noti, &nsound_type, &nsound_path); + DBG("Sound : %d, %s", nsound_type, nsound_path); + if (nsound_type > NOTIFICATION_SOUND_TYPE_NONE + || nsound_type < NOTIFICATION_SOUND_TYPE_MAX) { + + switch (nsound_type) { + case NOTIFICATION_SOUND_TYPE_DEFAULT: + feedback_play_type(FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_UNLOCK); + break; + case NOTIFICATION_SOUND_TYPE_USER_DATA: + quickpanel_player_play(SOUND_TYPE_NOTIFICATION, nsound_path); + break; + default: + break; + } + } + /* Play Vibration */ + notification_vibration_type_e nvibration_type = + NOTIFICATION_VIBRATION_TYPE_NONE; + const char *nvibration_path = NULL; + + notification_get_vibration(noti, &nvibration_type, &nvibration_path); + DBG("Vibration : %d, %s", nvibration_type, nvibration_path); + if (nvibration_type > NOTIFICATION_VIBRATION_TYPE_NONE + || nvibration_type < NOTIFICATION_VIBRATION_TYPE_MAX) { + + switch (nvibration_type) { + case NOTIFICATION_SOUND_TYPE_DEFAULT: + feedback_play_type(FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_GENERAL); + break; + case NOTIFICATION_SOUND_TYPE_USER_DATA: + break; + default: + break; + } + } + + /* Skip if previous ticker is still shown */ + if (g_ticker != NULL) { + _quickpanel_ticker_hide(NULL); + } + + /* Check tickernoti flag */ + notification_get_property(noti, &flags); + + if (flags & NOTIFICATION_PROP_DISABLE_TICKERNOTI) { + INFO("NOTIFICATION_PROP_DISABLE_TICKERNOTI"); + __ticker_only_noti_del(noti); + notification_free(noti); + } else if (applist & NOTIFICATION_DISPLAY_APP_TICKER) { + /* Display ticker */ + if (g_timer) + ecore_timer_del(g_timer); + + g_ticker = _quickpanel_ticker_create_tickernoti(noti); + if (g_ticker == NULL) { + ERR("Fail to create tickernoti"); + __ticker_only_noti_del(noti); + notification_free(noti); + return; + } + + g_timer = ecore_timer_add(QP_TICKER_DURATION, + _quickpanel_ticker_timeout_cb, noti); + + _quickpanel_ticker_win_rotated(data); + evas_object_show(g_ticker); + + evas_object_event_callback_add(g_ticker, EVAS_CALLBACK_SHOW, + _quickpanel_ticker_detail_show_cb, + g_ticker); + evas_object_event_callback_add(g_ticker, EVAS_CALLBACK_HIDE, + _quickpanel_ticker_detail_hide_cb, + noti); + evas_object_smart_callback_add(g_ticker, "clicked", + _quickpanel_ticker_clicked_cb, + noti); + } +} + +/***************************************************************************** + * + * Util functions + * + *****************************************************************************/ +static int quickpanel_ticker_init(void *data) +{ + struct appdata *ad = (struct appdata *)data; + + latest_inserted_time = time(NULL); + g_window = ad->win; + + notification_register_detailed_changed_cb(_quickpanel_ticker_noti_detailed_changed_cb, + data); + + return QP_OK; +} + +static int quickpanel_ticker_fini(void *data) +{ + _quickpanel_ticker_hide(NULL); + + return QP_OK; +} + +static int quickpanel_ticker_enter_hib(void *data) +{ + return QP_OK; +} + +static int quickpanel_ticker_leave_hib(void *data) +{ + return QP_OK; +} + +static void quickpanel_ticker_reflesh(void *data) +{ + retif(data == NULL, , "Invalid parameter!"); + + if (g_ticker != NULL) { + _quickpanel_ticker_win_rotated(data); + } +} diff --git a/daemon/quickpanel-ui.c b/daemon/quickpanel-ui.c new file mode 100755 index 0000000..4deb6d5 --- /dev/null +++ b/daemon/quickpanel-ui.c @@ -0,0 +1,1156 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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 <stdio.h> +#include <signal.h> +#include <app.h> +#include <system_info.h> +#include <sys/utsname.h> +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <utilX.h> +#include <Ecore_X.h> +#include <Ecore_Input.h> +#include <heynoti.h> +#include <vconf.h> +#include <unistd.h> +#include <privilege-control.h> +#include <bundle.h> +#include <feedback.h> + +#include "common.h" +#include "quickpanel-ui.h" +#include "modules.h" +#include "notifications/noti_display_app.h" +#include "quickpanel_def.h" + +#define HIBERNATION_ENTER_NOTI "HIBERNATION_ENTER" +#define HIBERNATION_LEAVE_NOTI "HIBERNATION_LEAVE" + +#define QP_WINDOW_PRIO 300 +#define QP_PLAY_DURATION_LIMIT 15 + +/* heynoti handle */ +static int g_hdl_heynoti; +static player_h g_sound_player; +static Ecore_Timer *g_sound_player_timer; +struct appdata *g_app_data = NULL; + +/* binary information */ +#define QP_EMUL_STR "Emulator" + +static int common_cache_flush(void *evas); + +/***************************************************************************** + * + * HIBERNATION + * + ****************************************************************************/ +static void _hibernation_enter_cb(void *data) +{ + struct appdata *ad = data; + + INFO(" >>>>>>>>>>>>>>> ENTER HIBERNATION!! <<<<<<<<<<<<<<<< "); + hib_enter_modules(data); + if (ad) + common_cache_flush(ad->evas); +} + +static void _hibernation_leave_cb(void *data) +{ + hib_leave_modules(data); + INFO(" >>>>>>>>>>>>>>> LEAVE HIBERNATION!! <<<<<<<<<<<<<<<< "); +} + +/****************************************************************************** + * + * UI + * + ****************************************************************************/ +static Eina_Bool quickpanel_ui_refresh_cb(void *data) +{ + struct appdata *ad = NULL; + + retif(data == NULL, QP_FAIL, "Invalid parameter!"); + ad = data; + + INFO(" >>>>>>>>>>>>>>> Refresh QP modules!! <<<<<<<<<<<<<<<< "); + refresh_modules(data); + + if (ad->list) { + elm_genlist_realized_items_update(ad->list); + } + + quickpanel_init_size_genlist(ad); + quickpanel_ui_update_height(ad); + + return EINA_FALSE; +} + +static int common_cache_flush(void *evas) +{ + int file_cache; + int collection_cache; + int image_cache; + int font_cache; + + retif(evas == NULL, QP_FAIL, "Evas is NULL\n"); + + file_cache = edje_file_cache_get(); + collection_cache = edje_collection_cache_get(); + image_cache = evas_image_cache_get(evas); + font_cache = evas_font_cache_get(evas); + + edje_file_cache_set(file_cache); + edje_collection_cache_set(collection_cache); + evas_image_cache_set(evas, 0); + evas_font_cache_set(evas, 0); + + evas_image_cache_flush(evas); + evas_render_idle_flush(evas); + evas_font_cache_flush(evas); + + edje_file_cache_flush(); + edje_collection_cache_flush(); + + edje_file_cache_set(file_cache); + edje_collection_cache_set(collection_cache); + evas_image_cache_set(evas, image_cache); + evas_font_cache_set(evas, font_cache); + + return QP_OK; +} + +static int _resize_noti_win(void *data, int new_angle) +{ + struct appdata *ad = (struct appdata *)data; + int w = 0, h = 0; + int tot_h = 0; + int diff = 0; + + diff = (ad->angle > new_angle) ? + (ad->angle - new_angle) : (new_angle - ad->angle); + +#if 0 + int tot_h = QP_HANDLE_H * ad->scale; + + /* get indicator height */ + ecore_x_e_illume_indicator_geometry_get(ecore_x_window_root_first_get(), + NULL, NULL, NULL, &h); + if (h <= 0) + h = (int)(QP_INDICATOR_H * ad->scale); + + tot_h += h; + INFO("tot_h[%d], scale[%lf],indi[%d]", tot_h, ad->scale, h); +#else + tot_h = 0; + INFO("tot_h[%d], scale[%lf]", tot_h, ad->scale); +#endif + + ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, &h); + if (diff % 180 != 0) { + int width = 0; + int height = 0; + if (ad->angle % 180 == 0) { + width = w - tot_h; + height = h; + } else { + width = h - tot_h; + height = w; + } + INFO("win[%dx%d], Resize[%dx%d] diff[%d], angle[%d]", + w, h, width, height, diff, ad->angle); + evas_object_resize(ad->win, (int)width-1, (int)height-1); //workaround + evas_object_resize(ad->win, (int)width, (int)height); + } + return 0; +} + +static Eina_Bool quickpanel_hardkey_cb(void *data, int type, void *event) +{ + struct appdata *ad = NULL; + Ecore_Event_Key *key_event = NULL; + Ecore_X_Window xwin; + + retif(data == NULL || event == NULL, + EINA_FALSE, "Invalid parameter!"); + ad = data; + key_event = event; + + if (!strcmp(key_event->keyname, KEY_SELECT)) { + xwin = elm_win_xwindow_get(ad->win); + if (xwin != 0) + ecore_x_e_illume_quickpanel_state_send(ecore_x_e_illume_zone_get(xwin),ECORE_X_ILLUME_QUICKPANEL_STATE_OFF); + } + return EINA_FALSE; +} + +static Eina_Bool quickpanel_ui_client_message_cb(void *data, int type, + void *event) +{ + struct appdata *ad = data; + Ecore_X_Event_Client_Message *ev = event; + int new_angle; + + retif(data == NULL || event == NULL, + ECORE_CALLBACK_RENEW, "Invalid parameter!"); + + if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) { + new_angle = ev->data.l[0]; + + if (new_angle == 0 || new_angle == 90 || new_angle == 180 || new_angle == 270) { + if (new_angle != ad->angle) { + INFO("ROTATION: new:%d old:%d", new_angle, ad->angle); + _resize_noti_win(ad, new_angle); + + elm_win_rotation_with_resize_set(ad->win, + new_angle); + ad->angle = new_angle; + + quickpanel_ui_set_indicator_cover(ad); + } + } + ecore_idler_add(quickpanel_ui_refresh_cb, ad); + } else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE) { + if (ev->data.l[0] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON) { + qp_opened_modules(data); + } else { + qp_closed_modules(data); + } + } + return ECORE_CALLBACK_RENEW; +} + +static Evas_Object *_quickpanel_ui_window_add(const char *name, int prio) +{ + Evas_Object *eo = NULL; + Ecore_X_Window xwin; + + eo = elm_win_add(NULL, name, ELM_WIN_BASIC); + + if (eo != NULL) { + elm_win_alpha_set(eo, EINA_TRUE); + elm_win_indicator_mode_set(eo, ELM_WIN_INDICATOR_SHOW); + elm_win_title_set(eo, name); + elm_win_borderless_set(eo, EINA_TRUE); + elm_win_autodel_set(eo, EINA_TRUE); + + /* set this window as a quickpanel */ + elm_win_quickpanel_set(eo, 1); + elm_win_quickpanel_priority_major_set(eo, prio); + + /* icccm name class set */ + xwin = elm_win_xwindow_get(eo); + ecore_x_icccm_name_class_set(xwin, "QUICKPANEL", "QUICKPANEL"); + evas_object_show(eo); + } + + return eo; +} + +Evas_Object *quickpanel_ui_load_edj(Evas_Object * parent, const char *file, + const char *group, int is_just_load) +{ + Eina_Bool r; + Evas_Object *eo = NULL; + + retif(parent == NULL, NULL, "Invalid parameter!"); + + eo = elm_layout_add(parent); + retif(eo == NULL, NULL, "Failed to add layout object!"); + + r = elm_layout_file_set(eo, file, group); + retif(r != EINA_TRUE, NULL, + "Failed to set edje object file[%s-%s]!", file, group); + + evas_object_size_hint_weight_set(eo, + EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + + if (is_just_load == 1) { + elm_win_resize_object_add(parent, eo); + } + evas_object_show(eo); + + return eo; +} + +static void _quickpanel_ui_close_quickpanel(void *data, Evas_Object *o, + const char *emission, const char *source) { + + Ecore_X_Window xwin = 0; + struct appdata *ad = NULL; + + retif(data == NULL, , "data is NULL"); + ad = data; + + DBG("close quick panel"); + + xwin = elm_win_xwindow_get(ad->win); + + if (xwin != 0) + ecore_x_e_illume_quickpanel_state_send(ecore_x_e_illume_zone_get(xwin),ECORE_X_ILLUME_QUICKPANEL_STATE_OFF); +} + +static int _quickpanel_ui_create_win(void *data) +{ + struct appdata *ad = data; + int w = 0; + int h = 0; + + retif(data == NULL, QP_FAIL, "Invialid parameter!"); + + ad->win = _quickpanel_ui_window_add("Quickpanel Window", + QP_WINDOW_PRIO); + if (ad->win == NULL) { + ERR("ui create : failed to create window."); + return -1; + } +#ifdef QP_INDICATOR_WIDGET_ENABLE + ad->comformant = elm_conformant_add(ad->win); + elm_object_style_set(ad->comformant, "nokeypad"); + + ad->ly = quickpanel_ui_load_edj(ad->comformant, + DEFAULT_EDJ, "quickpanel/gl_base", 0); + if (ad->ly == NULL) + return -1; + + evas_object_size_hint_weight_set(ad->comformant, + EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(ad->win, ad->comformant); + evas_object_show(ad->comformant); + elm_object_content_set(ad->comformant, ad->ly); + +#else + ad->ly = quickpanel_ui_load_edj(ad->win, + DEFAULT_EDJ, "quickpanel/gl_base", 0); + if (ad->ly == NULL) + return -1; +#endif + + /* get noti evas */ + ad->evas = evas_object_evas_get(ad->win); + + ad->list = elm_genlist_add(ad->ly); + if (!ad->list) { + ERR("failed to elm_genlist_add"); + evas_object_del(ad->ly); + evas_object_del(ad->win); + ad->ly = NULL; + ad->win = NULL; + ad->evas = NULL; + return -1; + } + elm_genlist_homogeneous_set(ad->list, EINA_FALSE); + elm_scroller_policy_set(ad->list, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_OFF); + elm_object_part_content_set(ad->ly, "qp.gl_base.gl.swallow", ad->list); + + ecore_x_window_size_get(ecore_x_window_root_first_get(), &w, &h); + evas_object_resize(ad->win, w, h); + + ad->win_width = w; + ad->win_height = h; + + edje_object_signal_callback_add(_EDJ(ad->ly), + "close.quickpanel", "*", _quickpanel_ui_close_quickpanel, + ad); + + quickpanel_init_size_genlist(ad); + + quickpanel_ui_set_indicator_cover(ad); + + /* key grab */ + utilx_grab_key(ecore_x_display_get(), elm_win_xwindow_get(ad->win), KEY_SELECT, SHARED_GRAB); + + return 0; +} + + +void quickpanel_ui_set_indicator_cover(void *data) +{ + retif(data == NULL, , "data is NULL"); + struct appdata *ad = data; + + int x_1 = 0, y_1 = 0; + int x_2 = 0, y_2 = 0; + int angle = ad->angle; + + int width = INDICATOR_COVER_W * ad->scale; + int height = INDICATOR_COVER_H * ad->scale; + + switch (angle) { + case 0: + x_1 = 0; + y_1 = 0; + x_2 = ad->win_width - width; + y_2 = 0; + break; + case 90: + x_1 = 0; + y_1 = 0; + x_2 = ad->win_height - width; + y_2 = 0; + break; + case 180: + x_1 = 0; + y_1 = 0; + x_2 = ad->win_width - width; + y_2 = 0; + break; + case 270: + x_1 = 0; + y_1 = 0; + x_2 = ad->win_height - width; + y_2 = 0; + break; + } + + if (ad->cover_indicator_left == NULL) { + Evas_Object *bg = evas_object_rectangle_add(ad->evas); + evas_object_color_set(bg, 52, 52, 50, 255); // opaque white background + evas_object_repeat_events_set(bg, EINA_FALSE); + evas_object_resize(bg, width, height); // covers full canvas + evas_object_move(bg, x_1, y_1); + evas_object_show(bg); + ad->cover_indicator_left = bg; + } else { + evas_object_move(ad->cover_indicator_left, x_1, y_1); + } + if (ad->cover_indicator_right == NULL) { + Evas_Object *bg = evas_object_rectangle_add(ad->evas); + evas_object_color_set(bg, 52, 52, 50, 255); // opaque white background + evas_object_repeat_events_set(bg, EINA_FALSE); + evas_object_resize(bg, width, height); // covers full canvas + evas_object_move(bg, x_2, y_2); + evas_object_show(bg); + ad->cover_indicator_right = bg; + } else { + evas_object_move(ad->cover_indicator_right, x_2, y_2); + } +} + +void quickpanel_ui_window_set_input_region(void *data, int contents_height) +{ + struct appdata *ad = NULL; + Ecore_X_Window xwin; + Ecore_X_Atom atom_window_input_region = 0; + unsigned int window_input_region[4] = {0,}; + + retif(data == NULL, , "Invialid parameter!"); + ad = data; + + xwin = elm_win_xwindow_get(ad->win); + + DBG("angle:%d", ad->angle); + switch (ad->angle) { + case 0: + window_input_region[0] = 0; //X + window_input_region[1] = contents_height; // Y + window_input_region[2] = ad->win_width; // Width + window_input_region[3] = ad->scale * QP_HANDLE_H; // height + break; + case 90: + window_input_region[0] = contents_height; //X + window_input_region[1] = 0; // Y + window_input_region[2] = ad->scale * QP_HANDLE_H; // Width + window_input_region[3] = ad->win_height; // height + break; + case 180: + window_input_region[0] = 0; //X + window_input_region[1] = ad->win_height - contents_height - ad->scale * QP_HANDLE_H; // Y + window_input_region[2] = ad->win_width; // Width + window_input_region[3] = ad->scale * QP_HANDLE_H; // height + break; + case 270: + window_input_region[0] = ad->win_width - contents_height - ad->scale * QP_HANDLE_H ; //X + window_input_region[1] = 0; // Y + window_input_region[2] = ad->scale * QP_HANDLE_H; // Width + window_input_region[3] = ad->win_height; // height + break; + } + + DBG("win_input_0:%d\nwin_input_1:%d\nwin_input_2:%d\nwin_input_3:%d\n" + ,window_input_region[0] + ,window_input_region[1] + ,window_input_region[2] + ,window_input_region[3] + ); + + atom_window_input_region = ecore_x_atom_get(STR_ATOM_WINDOW_INPUT_REGION); + ecore_x_window_prop_card32_set(xwin, atom_window_input_region, window_input_region, 4); +} + +void quickpanel_ui_window_set_content_region(void *data, int contents_height) +{ + struct appdata *ad = NULL; + Ecore_X_Window xwin; + Ecore_X_Atom atom_window_contents_region = 0; + unsigned int window_contents_region[4] = {0,}; + + retif(data == NULL, , "Invialid parameter!"); + ad = data; + + xwin = elm_win_xwindow_get(ad->win); + + DBG("angle:%d", ad->angle); + switch (ad->angle) { + case 0: + window_contents_region[0] = 0; //X + window_contents_region[1] = 0; // Y + window_contents_region[2] = ad->win_width; // Width + window_contents_region[3] = contents_height; // height + break; + case 90: + window_contents_region[0] = 0; //X + window_contents_region[1] = 0; // Y + window_contents_region[2] = contents_height; // Width + window_contents_region[3] = ad->win_height; // height + break; + case 180: + window_contents_region[0] = 0; //X + window_contents_region[1] = ad->win_height - contents_height; // Y + window_contents_region[2] = ad->win_width; // Width + window_contents_region[3] = contents_height; // height + break; + case 270: + window_contents_region[0] = ad->win_width - contents_height ; //X + window_contents_region[1] = 0; // Y + window_contents_region[2] = contents_height; // Width + window_contents_region[3] = ad->win_height; // height + break; + } + + DBG("win_contents_0:%d\nwin_contents_1:%d\nwin_contents_2:%d\nwin_contents_3:%d\n" + ,window_contents_region[0] + ,window_contents_region[1] + ,window_contents_region[2] + ,window_contents_region[3] + ); + + atom_window_contents_region = ecore_x_atom_get(STR_ATOM_WINDOW_CONTENTS_REGION); + ecore_x_window_prop_card32_set(xwin, atom_window_contents_region, window_contents_region, 4); +} + +static void _quickpanel_move_data_to_service(const char *key, const char *val, void *data) +{ + retif(data == NULL || key == NULL || val == NULL, , "Invialid parameter!"); + + service_h service = data; + service_add_extra_data(service, key, val); +} + +int quickpanel_launch_app(char *app_id, void *data) +{ + int ret = SERVICE_ERROR_NONE; + service_h service = NULL; + + retif(app_id == NULL, SERVICE_ERROR_INVALID_PARAMETER, "Invialid parameter!"); + + ret = service_create(&service); + if (ret != SERVICE_ERROR_NONE) { + DBG("service_create() return error : %d", ret); + return ret; + } + retif(service == NULL, SERVICE_ERROR_INVALID_PARAMETER, "fail to create service handle!"); + + service_set_operation(service, SERVICE_OPERATION_DEFAULT); + service_set_app_id(service, app_id); + + if (data != NULL) { + bundle_iterate((bundle *)data, _quickpanel_move_data_to_service, service); + } + + ret = service_send_launch_request(service, NULL, NULL); + if (ret != SERVICE_ERROR_NONE) { + DBG("service_send_launch_request() is failed : %d", ret); + service_destroy(service); + return ret; + } + service_destroy(service); + return ret; +} + +static void _quickpanel_player_free(player_h *sound_player) +{ + retif(sound_player == NULL, , "invalid parameter"); + + player_state_e state = PLAYER_STATE_NONE; + + if (*sound_player != NULL) { + if (player_get_state(*sound_player, &state) == PLAYER_ERROR_NONE) { + + DBG("state of player %d", state); + + if (state == PLAYER_STATE_PLAYING) { + player_stop(*sound_player); + player_unprepare(*sound_player); + } + if (state == PLAYER_STATE_READY) { + player_unprepare(*sound_player); + } + } + player_destroy(*sound_player); + *sound_player = NULL; + } +} + +static void +_quickpanel_player_del_timeout_timer(void) +{ + if (g_sound_player_timer) { + ecore_timer_del(g_sound_player_timer); + g_sound_player_timer = NULL; + } +} + +static Eina_Bool _quickpanel_player_timeout_cb(void *data) +{ + g_sound_player_timer = NULL; + + retif(data == NULL, ECORE_CALLBACK_CANCEL, "invalid parameter"); + player_h *sound_player = data; + + _quickpanel_player_free(sound_player); + + return ECORE_CALLBACK_CANCEL; +} + +static void +_quickpanel_player_completed_cb(void *user_data) +{ + retif(user_data == NULL, , "invalid parameter"); + player_h *sound_player = user_data; + + _quickpanel_player_del_timeout_timer(); + _quickpanel_player_free(sound_player); +} + +static void +_quickpanel_player_interrupted_cb(player_interrupted_code_e code, void *user_data) +{ + retif(user_data == NULL, , "invalid parameter"); + player_h *sound_player = user_data; + + _quickpanel_player_del_timeout_timer(); + _quickpanel_player_free(sound_player); +} + +static void +_quickpanel_player_error_cb(int error_code, void *user_data) +{ + retif(user_data == NULL, , "invalid parameter"); + player_h *sound_player = user_data; + + _quickpanel_player_del_timeout_timer(); + _quickpanel_player_free(sound_player); +} + +void quickpanel_player_play(sound_type_e sound_type, const char *sound_file) +{ + player_h *sound_player = &g_sound_player; + + int ret = PLAYER_ERROR_NONE; + player_state_e state = PLAYER_STATE_NONE; + + _quickpanel_player_del_timeout_timer(); + + if (*sound_player != NULL) { + _quickpanel_player_free(sound_player); + } + + ret = player_create(sound_player); + if (ret != PLAYER_ERROR_NONE) { + ERR("creating the player handle failed[%d]", ret); + player_destroy(*sound_player); + } + + ret = player_set_sound_type(*sound_player, SOUND_TYPE_MEDIA); + if (ret != PLAYER_ERROR_NONE) { + ERR("player_set_sound_type() ERR: %x!!!!", ret); + _quickpanel_player_free(sound_player); + return ; + } + + player_get_state(*sound_player, &state); + if (state > PLAYER_STATE_READY) { + _quickpanel_player_free(sound_player); + return; + } + + ret = player_set_uri(*sound_player, sound_file); + if (ret != PLAYER_ERROR_NONE) { + DBG("set attribute---profile_uri[%d]", ret); + _quickpanel_player_free(sound_player); + return; + } + + ret = player_prepare(*sound_player); + if (ret != PLAYER_ERROR_NONE) { + DBG("realizing the player handle failed[%d]", ret); + _quickpanel_player_free(sound_player); + return; + } + + player_get_state(*sound_player, &state); + if (state != PLAYER_STATE_READY) { + DBG("state of player is invalid %d", state); + _quickpanel_player_free(sound_player); + return; + } + + /* register callback */ + ret = player_set_completed_cb(*sound_player, _quickpanel_player_completed_cb, sound_player); + if (ret != PLAYER_ERROR_NONE) { + DBG("player_set_completed_cb() ERR: %x!!!!", ret); + _quickpanel_player_free(sound_player); + return; + } + + ret = player_set_interrupted_cb(*sound_player, _quickpanel_player_interrupted_cb, sound_player); + if (ret != PLAYER_ERROR_NONE) { + _quickpanel_player_free(sound_player); + return; + } + + ret = player_set_error_cb(*sound_player, _quickpanel_player_error_cb, sound_player); + if (ret != PLAYER_ERROR_NONE) { + _quickpanel_player_free(sound_player); + return; + } + + ret = player_start(*sound_player); + if (ret != PLAYER_ERROR_NONE) { /* if directly return retor.. */ + DBG("player_start [%d]", ret); + _quickpanel_player_free(sound_player); + return; + } + + g_sound_player_timer = ecore_timer_add(QP_PLAY_DURATION_LIMIT, + _quickpanel_player_timeout_cb, sound_player); +} + +static int _quickpanel_ui_delete_win(void *data) +{ + struct appdata *ad = data; + retif(data == NULL, QP_FAIL, "Invialid parameter!"); + + if (ad->ly != NULL) { + evas_object_del(ad->ly); + ad->ly = NULL; + } + if (ad->win != NULL) { + evas_object_del(ad->win); + ad->win = NULL; + } + + return QP_OK; +} + +static void _quickpanel_ui_init_heynoti(struct appdata *ad) +{ + int ret = 0; + + /* init heynoti */ + g_hdl_heynoti = heynoti_init(); + if (g_hdl_heynoti == -1) { + ERR("ui init heynoti : fail to heynoti_init."); + g_hdl_heynoti = 0; + return; + } + + /* subscribe hibernation */ + heynoti_subscribe(g_hdl_heynoti, HIBERNATION_ENTER_NOTI, + _hibernation_enter_cb, (void *)ad); + heynoti_subscribe(g_hdl_heynoti, HIBERNATION_LEAVE_NOTI, + _hibernation_leave_cb, (void *)ad); + + ret = heynoti_attach_handler(g_hdl_heynoti); + if (ret == -1) { + ERR("ui init heynoti : fail to heynoti_attach_handler."); + return; + } +} + +static void _quickpanel_ui_fini_heynoti(void) +{ + if (g_hdl_heynoti != 0) { + /* unsubscribe hibernation */ + heynoti_unsubscribe(g_hdl_heynoti, HIBERNATION_ENTER_NOTI, + _hibernation_enter_cb); + heynoti_unsubscribe(g_hdl_heynoti, HIBERNATION_LEAVE_NOTI, + _hibernation_leave_cb); + + /* close heynoti */ + heynoti_close(g_hdl_heynoti); + g_hdl_heynoti = 0; + } +} + +static void _quickpanel_ui_init_ecore_event(struct appdata *ad) +{ + Ecore_Event_Handler *hdl = NULL; + Ecore_Event_Handler *hdl_key = NULL; + + /* Register window rotate event */ + hdl = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, + quickpanel_ui_client_message_cb, ad); + if (hdl == NULL) + ERR("failed to add handler(ECORE_X_EVENT_CLIENT_MESSAGE)"); + + ad->hdl_client_message = hdl; + + hdl_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, quickpanel_hardkey_cb, ad); + if (hdl_key == NULL) + ERR("failed to add handler(ECORE_EVENT_KEY_UP)"); + + ad->hdl_hardkey = hdl_key; +} + +static void _quickpanel_ui_fini_ecore_event(struct appdata *ad) +{ + if (ad->hdl_client_message != NULL) { + ecore_event_handler_del(ad->hdl_client_message); + ad->hdl_client_message = NULL; + } + if (ad->hdl_hardkey != NULL) { + ecore_event_handler_del(ad->hdl_hardkey); + ad->hdl_hardkey = NULL; + } +} +int quickpanel_ui_check_emul(void) +{ + int is_emul = 0; + char *info = NULL; + + if (system_info_get_value_string(SYSTEM_INFO_KEY_MODEL, &info) == 0) { + if (info == NULL) return 0; + if (!strncmp(QP_EMUL_STR, info, strlen(info))) { + is_emul = 1; + } + } + + if (info != NULL) free(info); + + return is_emul; +} + +static void _quickpanel_ui_setting_show(struct appdata *ad, int show) +{ + if (!ad) + return; + + if (!ad->ly) + return; + + ad->show_setting = 1; + +} + +#ifdef QP_BRIGHTNESS_ENABLE +/* toggle */ +extern QP_Module brightness_ctrl; +#endif /* QP_BRIGHTNESS_ENABLE */ +#ifdef QP_MINICTRL_ENABLE +extern QP_Module minictrl; +#endif /* QP_MINICTRL_ENABLE */ +extern QP_Module noti; + +static void _quickpanel_ui_update_height(void *data) +{ + int contents_height = 0; + int height_genlist = 0; + + struct appdata *ad = NULL; + + retif(data == NULL, , "data is NULL"); + ad = data; + + DBG("current item count:%d", elm_genlist_items_count(ad->list)); + + height_genlist += noti.get_height(data); +#ifdef QP_BRIGHTNESS_ENABLE + height_genlist += brightness_ctrl.get_height(data); +#endif +#ifdef QP_MINICTRL_ENABLE + height_genlist += minictrl.get_height(data); +#endif + + height_genlist = ad->gl_limit_height; + + contents_height = ad->gl_distance_from_top + height_genlist + ad->gl_distance_to_bottom - ad->scale * QP_HANDLE_H; + + DBG("height_genlist:%d\n gl_distance_from_top:%d\n gl_distance_to_bottom:%d\n gl_limit_height:%d\nnew_height:%d" + ,height_genlist + ,ad->gl_distance_from_top + ,ad->gl_distance_to_bottom + ,ad->gl_limit_height + ,contents_height + ); + + quickpanel_ui_window_set_input_region(ad, contents_height); + quickpanel_ui_window_set_content_region(ad, contents_height); +} + +void quickpanel_ui_update_height(void *data) +{ + _quickpanel_ui_update_height(data); +} + +void quickpanel_init_size_genlist(void *data) +{ + struct appdata *ad = NULL; + int max_height_window = 0; + Evas_Coord genlist_y = 0; + Evas_Coord spn_height = 0; + + retif(data == NULL, , "data is NULL"); + ad = data; + + if (ad->angle == 90 || ad->angle == 270 ) + max_height_window = ad->win_width; + else + max_height_window = ad->win_height; + + edje_object_part_geometry_get(_EDJ(ad->ly), "qp.gl_base.gl.swallow", NULL, &genlist_y, NULL, NULL); + DBG("quickpanel, qp.gl_base.gl.swallow y: %d",genlist_y); + + edje_object_part_geometry_get(_EDJ(ad->ly), "qp.base.spn.swallow", NULL, NULL, NULL, &spn_height); + DBG("quickpanel, to spn_height: %d",spn_height); + + ad->gl_distance_from_top = genlist_y; + ad->gl_distance_to_bottom = spn_height + (1 * ad->scale) + (ad->scale*QP_HANDLE_H) ; + ad->gl_limit_height = max_height_window - ad->gl_distance_from_top - ad->gl_distance_to_bottom; +} + +void *quickpanel_get_app_data(void) +{ + return g_app_data; +} + +/***************************************************************************** + * + * App efl main interface + * + ****************************************************************************/ + +static void _signal_handler(int signum, siginfo_t *info, void *unused) +{ + DBG("Terminated..."); + app_efl_exit(); +} + +static void _heynoti_event_power_off(void *data) +{ + DBG("Terminated..."); + app_efl_exit(); +} + +static bool quickpanel_app_create(void *data) +{ + DBG(""); + + pid_t pid; + int r; + + // signal handler + struct sigaction act; + act.sa_sigaction = _signal_handler; + act.sa_flags = SA_SIGINFO; + + int ret = sigemptyset(&act.sa_mask); + if (ret < 0) { + ERR("Failed to sigemptyset[%s]", strerror(errno)); + } + ret = sigaddset(&act.sa_mask, SIGTERM); + if (ret < 0) { + ERR("Failed to sigaddset[%s]", strerror(errno)); + } + ret = sigaction(SIGTERM, &act, NULL); + if (ret < 0) { + ERR("Failed to sigaction[%s]", strerror(errno)); + } + + pid = setsid(); + if (pid < 0) + WARN("Failed to set session id!"); + + r = nice(2); + if (r == -1) + WARN("Failed to set nice value!"); + + return TRUE; +} + +static void quickpanel_app_terminate(void *data) +{ + DBG(""); + + struct appdata *ad = data; + retif(ad == NULL, , "invalid data."); + + /* fini quickpanel modules */ + fini_modules(ad); + + common_cache_flush(ad->evas); + + feedback_deinitialize(); + + /* unregister system event callback */ + _quickpanel_ui_fini_heynoti(); + + notification_daemon_shutdown(); + + _quickpanel_ui_fini_ecore_event(ad); + + if (ad->cover_indicator_left != NULL) { + evas_object_del(ad->cover_indicator_left); + ad->cover_indicator_left = NULL; + } + if (ad->cover_indicator_right != NULL) { + evas_object_del(ad->cover_indicator_right); + ad->cover_indicator_right = NULL; + } + /* delete quickpanel window */ + _quickpanel_ui_delete_win(ad); + + INFO(" >>>>>>>>>>>>>>> QUICKPANEL IS TERMINATED!! <<<<<<<<<<<<<<<< "); +} + +static void quickpanel_app_pause(void *data) +{ + DBG(""); + + struct appdata *ad = data; + retif(ad == NULL,, "invalid data."); + + suspend_modules(ad); + + common_cache_flush(ad->evas); +} + +static void quickpanel_app_resume(void *data) +{ + DBG(""); + + struct appdata *ad = data; + retif(ad == NULL,, "invalid data."); + + resume_modules(data); +} + +static void quickpanel_app_service(service_h service, void *data) +{ + struct appdata *ad = data; + int ret = 0; + + retif(ad == NULL, , "Invialid parameter!"); + + INFO(" >>>>>>>>>>>>>>> QUICKPANEL IS STARTED!! <<<<<<<<<<<<<<<< "); + + /* Check emulator */ + ad->is_emul = quickpanel_ui_check_emul(); + INFO("quickpanel run in %s", ad->is_emul ? "Emul" : "Device"); + + ad->scale = elm_config_scale_get(); + if (ad->scale < 0) + ad->scale = 1.0; + + /* Get theme */ + elm_theme_extension_add(NULL, DEFAULT_THEME_EDJ); + + /* create quickpanel window */ + ret = _quickpanel_ui_create_win(ad); + retif(ret != QP_OK, , "Failed to create window!"); + + /* init internationalization */ + notification_daemon_win_set(ad->win); + + _quickpanel_ui_init_ecore_event(ad); + + _quickpanel_ui_init_heynoti(ad); + + feedback_initialize(); + +#ifdef QP_SETTING_ENABLE + _quickpanel_ui_setting_show(ad, 1); +#else /* QP_SETTING_ENABLE */ + _quickpanel_ui_setting_show(ad, 0); +#endif /* QP_SETTING_ENABLE */ + + /* init quickpanel modules */ + init_modules(ad); + + ecore_idler_add(quickpanel_ui_refresh_cb, ad); +} + +static void quickpanel_app_language_changed_cb(void *data) +{ + retif(data == NULL, , "Invalid parameter!"); + + INFO(" >>>>>>>>>>>>>>> LANGUAGE CHANGED!! <<<<<<<<<<<<<<<< "); + lang_change_modules(data); +} + +static void quickpanel_app_region_format_changed_cb(void *data) +{ + INFO(" >>>>>>>>>>>>>>> region_format CHANGED!! <<<<<<<<<<<<<<<< "); +} + +int main(int argc, char *argv[]) +{ + int r = 0; + struct appdata ad; + app_event_callback_s app_callback = {0,}; + + r = control_privilege(); + if (r != 0) { + WARN("Failed to control privilege!"); + } + + int heyfd = heynoti_init(); + if (heyfd > 0) { + int ret = heynoti_subscribe(heyfd, "power_off_start", _heynoti_event_power_off, NULL); + if (ret > 0) { + ret = heynoti_attach_handler(heyfd); + if (ret < 0) { + ERR("Failed to heynoti_attach_handler[%d]", ret); + } + } else { + ERR("Failed to heynoti_subscribe[%d]", ret); + } + } else { + ERR("Failed to heynoti_init[%d]", heyfd); + } + + app_callback.create = quickpanel_app_create; + app_callback.terminate = quickpanel_app_terminate; + app_callback.pause = quickpanel_app_pause; + app_callback.resume = quickpanel_app_resume; + app_callback.service = quickpanel_app_service; + app_callback.low_memory = NULL; + app_callback.low_battery = NULL; + app_callback.device_orientation = NULL; + app_callback.language_changed = quickpanel_app_language_changed_cb; + app_callback.region_format_changed = quickpanel_app_region_format_changed_cb; + + memset(&ad, 0x0, sizeof(struct appdata)); + + notification_daemon_init(); + + g_app_data = &ad; + + DBG("start main"); + return app_efl_main(&argc, &argv, &app_callback, (void *)&ad); +} diff --git a/daemon/quickpanel-ui.h b/daemon/quickpanel-ui.h new file mode 100755 index 0000000..e3ec9cf --- /dev/null +++ b/daemon/quickpanel-ui.h @@ -0,0 +1,123 @@ +/* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.0 (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. + */ + +#ifndef __QUICKPANEL_UI_H__ +#define __QUICKPANEL_UI_H__ + +#include <Elementary.h> +#include <player.h> + +#if !defined(VENDOR) +# define VENDOR "org.tizen" +#endif +#if !defined(PACKAGE) +# define PACKAGE "quickpanel" +#endif + +#if !defined(LOCALEDIR) +# define LOCALEDIR "/usr/apps/"VENDOR"."PACKAGE"/res/locale" +#endif + +#if !defined(EDJDIR) +# define EDJDIR "/usr/apps/"VENDOR"."PACKAGE"/res/edje" +#endif + +/* EDJ theme */ +#define DEFAULT_EDJ EDJDIR"/"PACKAGE".edj" +#define DEFAULT_THEME_EDJ EDJDIR"/"PACKAGE"_theme.edj" + +#define _EDJ(o) elm_layout_edje_get(o) +#define _S(str) dgettext("sys_string", str) +#undef _ +#define _(str) gettext(str) +#define _NOT_LOCALIZED(str) (str) + +#define STR_ATOM_WINDOW_INPUT_REGION "_E_COMP_WINDOW_INPUT_REGION" +#define STR_ATOM_WINDOW_CONTENTS_REGION "_E_COMP_WINDOW_CONTENTS_REGION" + +#define MAX_NAM_LEN 4096 + +#define INDICATOR_COVER_W 82 +#define INDICATOR_COVER_H 60 + +#define QP_SETTING_PKG_SETTING VENDOR".setting" +#define QP_SETTING_PKG_SETTING_EMUL "kto5jikgul.Settings" + +struct appdata { + Evas_Object *win; +#ifdef QP_INDICATOR_WIDGET_ENABLE + Evas_Object *comformant; +#endif + Evas_Object *ly; + Evas *evas; + + Evas_Object *list; + int angle; + double scale; + char *theme; + + int win_width; + int win_height; + int gl_limit_height; + int gl_distance_from_top; + int gl_distance_to_bottom; + + int is_emul; /* 0 : target, 1 : emul */ + int show_setting; + + Ecore_Event_Handler *hdl_client_message; + Ecore_Event_Handler *hdl_hardkey; + + E_DBus_Connection *dbus_connection; + E_DBus_Signal_Handler *dbus_handler_size; + E_DBus_Signal_Handler *dbus_handler_progress; + E_DBus_Signal_Handler *dbus_handler_content; + + Evas_Object *cover_indicator_left; + Evas_Object *cover_indicator_right; +}; + +typedef struct _QP_Module { + char *name; + /* func */ + int (*init) (void *); + int (*fini) (void *); + int (*suspend) (void *); + int (*resume) (void *); + int (*hib_enter) (void *); + int (*hib_leave) (void *); + void (*lang_changed) (void *); + void (*refresh) (void *); + unsigned int (*get_height) (void *); + void (*qp_opened) (void *); + void (*qp_closed) (void *); + + /* do not modify this area */ + /* internal data */ + Eina_Bool state; +} QP_Module; + +void quickpanel_player_play(sound_type_e sound_type, const char *sound_file); +int quickpanel_launch_app(char *app_id, void *data); +int quickpanel_ui_check_emul(void); +void quickpanel_init_size_genlist(void *data); +void quickpanel_ui_update_height(void *data); +void *quickpanel_get_app_data(void); +Evas_Object *quickpanel_ui_load_edj(Evas_Object * parent, const char *file, + const char *group, int is_just_load); +void quickpanel_ui_set_indicator_cover(void *data); + +#endif /* __QUICKPANEL_UI_H__ */ |