diff --git a/legacy/elementary/ChangeLog b/legacy/elementary/ChangeLog index 49553afc5b..ae893bbe17 100644 --- a/legacy/elementary/ChangeLog +++ b/legacy/elementary/ChangeLog @@ -845,3 +845,7 @@ * Add elm_dbus_menu to support D-Bus external menus. * Add main menu to elm_win, which can be exported via D-Bus * Add configuration: ELM_EXTERNAL_MENU, to switch between internal and external menus + +2012-12-20 Murilo Pinoti Belluzzo (mbelluzzo) + + * Add elm_systray to set a Status Notifier Item in the System Tray (D-Bus). diff --git a/legacy/elementary/NEWS b/legacy/elementary/NEWS index 9a4c6f1ae9..cd1a4b3db7 100644 --- a/legacy/elementary/NEWS +++ b/legacy/elementary/NEWS @@ -25,6 +25,7 @@ Additions: * Add elm_plug signals "image,deleted" (fixed typo) and "image,resized". * Add elm_dbus_menu to support D-Bus external menus. * Add configuration: ELM_EXTERNAL_MENU, to switch between internal and extenal menus + * Add elm_systray.[ch]: Add support to D-Bus systray icons. Improvements: diff --git a/legacy/elementary/src/bin/Makefile.am b/legacy/elementary/src/bin/Makefile.am index 657c6472ec..12bf6efaf8 100644 --- a/legacy/elementary/src/bin/Makefile.am +++ b/legacy/elementary/src/bin/Makefile.am @@ -124,6 +124,7 @@ test_slideshow.c \ test_spinner.c \ test_store.c \ test_sys_notify.c \ +test_systray.c \ test_table.c \ test_thumb.c \ test_toolbar.c \ diff --git a/legacy/elementary/src/bin/test.c b/legacy/elementary/src/bin/test.c index e571fea913..c491897b9e 100644 --- a/legacy/elementary/src/bin/test.c +++ b/legacy/elementary/src/bin/test.c @@ -178,6 +178,7 @@ void test_bubble(void *data, Evas_Object *obj, void *event_info); void test_segment_control(void *data, Evas_Object *obj, void *event_info); void test_store(void *data, Evas_Object *obj, void *event_info); void test_sys_notify(void *data, Evas_Object *obj, void *event_info); +void test_systray(void *data, Evas_Object *obj, void *event_info); void test_win_inline(void *data, Evas_Object *obj, void *event_info); void test_win_socket(void *data, Evas_Object *obj, void *event_info); void test_win_plug(void *data, Evas_Object *obj, void *event_info); @@ -727,6 +728,7 @@ add_tests: //------------------------------// ADD_TEST(NULL, "System", "Notification", test_sys_notify); + ADD_TEST(NULL, "System", "Systray Item", test_systray); //------------------------------// ADD_TEST(NULL, "Micellaneous", "Copy And Paste", test_cnp); diff --git a/legacy/elementary/src/bin/test_systray.c b/legacy/elementary/src/bin/test_systray.c new file mode 100644 index 0000000000..864c58f28c --- /dev/null +++ b/legacy/elementary/src/bin/test_systray.c @@ -0,0 +1,194 @@ +#ifdef HAVE_CONFIG_H +# include "elementary_config.h" +#endif +#include +#ifndef ELM_LIB_QUICKLAUNCH + +#define WIDTH 320 +#define HEIGHT 160 + +static Evas_Object *ai = NULL; +static Evas_Object *i = NULL; +static Evas_Object *r = NULL; +static Eo *item = NULL; + +static Eina_Bool +_ev_handler(void *data __UNUSED__, + int type __UNUSED__, + void *event __UNUSED__) +{ + Eina_Bool ret; + + printf("systray ready event\n"); + + eo_do(item, elm_obj_systray_register(&ret)); + + printf("Item Registration: "); + if (ret) + printf("OK!\n"); + else + printf("Failed!\n"); + + return ECORE_CALLBACK_DONE; +} + +static void +_bt_clicked(void *data __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + eo_do(item, elm_obj_systray_icon_name_set(elm_entry_entry_get(i))); + eo_do(item, elm_obj_systray_att_icon_name_set(elm_entry_entry_get(ai))); +} + +static void + _r_clicked(void *data __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + eo_do(item, elm_obj_systray_status_set(elm_radio_value_get(r))); +} + +static void +_menu_clicked(void *data, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + printf("Menu Item Clicked: %s\n", (const char *) data); +} + +void +test_systray(void *data __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) +{ + Evas_Object *win, *bx, *it; + Elm_Object_Item *it2; + int st = 1; + + Eina_Bool init_ok = elm_need_systray(); + + ecore_event_handler_add(ELM_EVENT_SYSTRAY_READY, + _ev_handler, NULL); + + win = elm_win_add(NULL, "Systray", ELM_WIN_BASIC); + elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); + elm_win_title_set(win, "Systemtray - Status Notifier Item"); + elm_win_autodel_set(win, EINA_TRUE); + + it = elm_menu_add(win); + elm_menu_item_add(it, NULL, NULL, "root 1", _menu_clicked, "root 1"); + it2 = elm_menu_item_add(it, NULL, NULL, "root 2", _menu_clicked, "root 2"); + elm_menu_item_add(it, it2, NULL, "item 1", _menu_clicked, "item 1"); + elm_menu_item_add(it, it2, NULL, "item 2", _menu_clicked, "item 2"); + + // Status Notifier Item Handler + item = eo_add(ELM_OBJ_SYSTRAY_CLASS, win); + eo_do(item, elm_obj_systray_icon_name_set("elementary")); + eo_do(item, elm_obj_systray_att_icon_name_set("elementary")); + eo_do(item, elm_obj_systray_menu_set(it)); + + it = elm_bg_add(win); + elm_win_resize_object_add(win, it); + evas_object_size_hint_min_set(it, WIDTH, HEIGHT); + evas_object_size_hint_max_set(it, WIDTH, HEIGHT); + evas_object_show(it); + + bx = elm_box_add(win); + evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, bx); + evas_object_show(bx); + + if (!init_ok) + { + it = elm_label_add(win); + evas_object_size_hint_align_set(it, 0, EVAS_HINT_FILL); + elm_object_text_set(it, "Systray initialization failed. " + "This test will do nothing."); + elm_box_pack_end(bx, it); + evas_object_show(it); + } + + it = elm_label_add(win); + evas_object_size_hint_align_set(it, 0, EVAS_HINT_FILL); + elm_object_text_set(it, "Icon:"); + elm_box_pack_end(bx, it); + evas_object_show(it); + + i = elm_entry_add(win); + elm_entry_single_line_set(i, EINA_TRUE); + elm_entry_scrollable_set(i, EINA_TRUE); + elm_entry_entry_set(i, "elementary"); + evas_object_size_hint_align_set(i, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(bx, i); + evas_object_show(i); + + it = elm_label_add(win); + evas_object_size_hint_align_set(it, 0, EVAS_HINT_FILL); + elm_object_text_set(it, "Attention Icon:"); + elm_box_pack_end(bx, it); + evas_object_show(it); + + ai = elm_entry_add(win); + elm_entry_single_line_set(ai, EINA_TRUE); + elm_entry_scrollable_set(ai, EINA_TRUE); + elm_entry_entry_set(ai, "elementary"); + evas_object_size_hint_align_set(ai, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(bx, ai); + evas_object_show(ai); + + it = elm_button_add(win); + elm_object_text_set(it, "Update"); + evas_object_smart_callback_add(it, "clicked", _bt_clicked, NULL); + elm_box_pack_end(bx, it); + evas_object_show(it); + + it = elm_separator_add(win); + elm_separator_horizontal_set(it, EINA_TRUE); + elm_box_pack_end(bx, it); + evas_object_show(it); + + it = elm_label_add(win); + evas_object_size_hint_align_set(it, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_text_set(it, "Status:"); + elm_box_pack_end(bx, it); + evas_object_show(it); + + it = elm_box_add(win); + elm_box_horizontal_set(it, EINA_TRUE); + elm_box_homogeneous_set(it, EINA_TRUE); + elm_box_pack_end(bx, it); + evas_object_show(it); + bx = it; + + r = elm_radio_add(win); + evas_object_size_hint_align_set(r, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_smart_callback_add(r, "changed", _r_clicked, NULL); + elm_radio_value_pointer_set(r, &st); + elm_radio_state_value_set(r, 0); + elm_object_text_set(r, "Passive"); + elm_box_pack_end(bx, r); + evas_object_show(r); + + it = elm_radio_add(win); + evas_object_size_hint_align_set(it, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_smart_callback_add(it, "changed", _r_clicked, NULL); + elm_radio_state_value_set(it, 1); + elm_radio_group_add(it, r); + elm_object_text_set(it, "Active"); + elm_box_pack_end(bx, it); + evas_object_show(it); + + it = elm_radio_add(win); + evas_object_size_hint_align_set(it, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_smart_callback_add(it, "changed", _r_clicked, NULL); + elm_radio_state_value_set(it, 2); + elm_radio_group_add(it, r); + elm_object_text_set(it, "Needs Attention"); + elm_box_pack_end(bx, it); + evas_object_show(it); + + evas_object_resize(win, WIDTH, HEIGHT); + evas_object_show(win); +} +#endif diff --git a/legacy/elementary/src/lib/Elementary.h.in b/legacy/elementary/src/lib/Elementary.h.in index 8787551dde..04b7b0bc85 100644 --- a/legacy/elementary/src/lib/Elementary.h.in +++ b/legacy/elementary/src/lib/Elementary.h.in @@ -163,6 +163,7 @@ EAPI extern Elm_Version *elm_version; #include #include +#include #include /* special widgets - types used elsewhere */ diff --git a/legacy/elementary/src/lib/Makefile.am b/legacy/elementary/src/lib/Makefile.am index b984aa4998..83205f00db 100644 --- a/legacy/elementary/src/lib/Makefile.am +++ b/legacy/elementary/src/lib/Makefile.am @@ -195,6 +195,8 @@ elm_slider.h \ elm_slideshow.h \ elm_spinner.h \ elm_store.h \ +elm_systray.h \ +elm_systray_watcher.h \ elm_sys_notify.h \ elm_table.h \ elm_theme.h \ @@ -283,6 +285,8 @@ elm_slider.c \ elm_slideshow.c \ elm_spinner.c \ elm_store.c \ +elm_systray.c \ +elm_systray_watcher.c \ elm_sys_notify.c \ elm_table.c \ elm_theme.c \ diff --git a/legacy/elementary/src/lib/elm_main.c b/legacy/elementary/src/lib/elm_main.c index 5526e06394..1bfa5cde23 100644 --- a/legacy/elementary/src/lib/elm_main.c +++ b/legacy/elementary/src/lib/elm_main.c @@ -649,6 +649,7 @@ elm_quicklaunch_shutdown(void) _elm_exit_handler = NULL; _elm_theme_shutdown(); + _elm_unneed_systray(); _elm_unneed_sys_notify(); _elm_unneed_efreet(); _elm_unneed_e_dbus(); diff --git a/legacy/elementary/src/lib/elm_need.h b/legacy/elementary/src/lib/elm_need.h index f488575ca7..4a4532b462 100644 --- a/legacy/elementary/src/lib/elm_need.h +++ b/legacy/elementary/src/lib/elm_need.h @@ -11,6 +11,20 @@ */ EAPI Eina_Bool elm_need_efreet(void); +/** + * Request that your elementary application needs Elm_Systray + * + * This initializes the Elm_Systray when called and, if support exists, + * returns EINA_TRUE, otherwise returns EINA_FALSE. This must be called + * before any elm_systray calls. + * + * @return EINA_TRUE if support exists and initialization succeeded. + * + * @ingroup Elm_Systray + * @since 1.8 + */ +EAPI Eina_Bool elm_need_systray(void); + /** * Request that your elementary application needs Elm_Sys_Notify * diff --git a/legacy/elementary/src/lib/elm_priv.h b/legacy/elementary/src/lib/elm_priv.h index acd13a5755..25f16d7b7b 100644 --- a/legacy/elementary/src/lib/elm_priv.h +++ b/legacy/elementary/src/lib/elm_priv.h @@ -328,6 +328,7 @@ void _elm_widget_top_win_focused_set(Evas_Object *obj, Eina_Bool top_win_focused); Eina_Bool _elm_widget_top_win_focused_get(const Evas_Object *obj); +void _elm_unneed_systray(void); void _elm_unneed_sys_notify(void); void _elm_unneed_ethumb(void); void _elm_unneed_web(void); diff --git a/legacy/elementary/src/lib/elm_systray.c b/legacy/elementary/src/lib/elm_systray.c new file mode 100644 index 0000000000..321b947348 --- /dev/null +++ b/legacy/elementary/src/lib/elm_systray.c @@ -0,0 +1,650 @@ +#include "Elementary.h" +#include "elm_priv.h" + +#include "Eo.h" + +EAPI Eo_Op ELM_OBJ_SYSTRAY_BASE_ID = EO_NOOP; + +#include "elm_systray_watcher.h" + +EAPI int ELM_EVENT_SYSTRAY_READY = 0; + +typedef struct _Elm_Systray_Private_Data +{ + Elm_Systray_Category cat; + Elm_Systray_Status status; + + const char *att_icon_name; + const char *icon_name; + const char *icon_theme_path; + const char *id; + const char *title; + const char *menu; + const Eo *menu_obj; +} Elm_Systray_Private_Data; + +static Elm_Systray_Private_Data _item = { + .cat = ELM_SYSTRAY_CATEGORY_APP_STATUS, + .status = ELM_SYSTRAY_STATUS_ACTIVE, + .att_icon_name = NULL, + .icon_name = NULL, + .icon_theme_path = NULL, + .id = NULL, + .title = NULL, + .menu = NULL, + .menu_obj = NULL +}; + +#ifdef ELM_EDBUS2 + +#define OBJ_PATH "/org/ayatana/NotificationItem/StatusNotifierItem" +#define INTERFACE "org.kde.StatusNotifierItem" + +static Eina_Bool _elm_need_systray = EINA_FALSE; + +static EDBus_Connection *_conn = NULL; +static EDBus_Service_Interface *_iface = NULL; + +static const char *_Elm_Systray_Cat_Str[] = { + [ELM_SYSTRAY_CATEGORY_APP_STATUS] = "ApplicationStatus", + [ELM_SYSTRAY_CATEGORY_COMMUNICATIONS] = "Communications", + [ELM_SYSTRAY_CATEGORY_SYS_SERVICES] = "SystemServices", + [ELM_SYSTRAY_CATEGORY_HARDWARE] = "Hardware", + [ELM_SYSTRAY_CATEGORY_OTHER] = "Other" +}; + +static const char *_Elm_Systray_Status_Str[] = { + [ELM_SYSTRAY_STATUS_ACTIVE] = "Active", + [ELM_SYSTRAY_STATUS_PASSIVE] = "Passive", + [ELM_SYSTRAY_STATUS_ATTENTION] = "NeedsAttention" +}; + +// ============================================================================= +// org.kde.StatusNotifierItem Service +// ============================================================================= +// ============================================================================= +// Methods +// ============================================================================= +static EDBus_Message * +_empty_method(const EDBus_Service_Interface *iface EINA_UNUSED, + const EDBus_Message *msg) +{ + return edbus_message_method_return_new(msg); +} + +static const EDBus_Method methods[] = { + { + "Scroll", + EDBUS_ARGS({"i", "delta"}, {"s", "orientation"}), + NULL, + _empty_method, + 0 + }, + { + "SecondaryActivate", + EDBUS_ARGS({"i", "x"}, {"i", "y"}), + NULL, + _empty_method, + 0 + }, + { + "XAyatanaSecondaryActivate", + EDBUS_ARGS({"u", "timestamp"}), + NULL, + _empty_method, + 0 + }, + { NULL, NULL, NULL, NULL, 0 } +}; + +// ============================================================================= +// Signals +// ============================================================================= +typedef enum _Elm_Systray_Service_Signals +{ + ELM_SYSTRAY_SIGNAL_NEWATTENTIONICON, + ELM_SYSTRAY_SIGNAL_NEWICON, + ELM_SYSTRAY_SIGNAL_NEWICONTHEMEPATH, + ELM_SYSTRAY_SIGNAL_NEWSTATUS, + ELM_SYSTRAY_SIGNAL_NEWTITLE, + ELM_SYSTRAY_SIGNAL_XAYATANANEWLABEL +} Elm_Systray_Service_Signals; + +#define _elm_systray_signal_emit(sig, ...) \ + edbus_service_signal_emit(_iface, sig, __VA_ARGS__) + +static const EDBus_Signal signals[] = { + [ELM_SYSTRAY_SIGNAL_NEWATTENTIONICON] = { + "NewAttentionIcon", NULL, 0 + }, + [ELM_SYSTRAY_SIGNAL_NEWICON] = { + "NewIcon", NULL, 0 + }, + [ELM_SYSTRAY_SIGNAL_NEWICONTHEMEPATH] = { + "NewIconThemePath", EDBUS_ARGS({"s", "icon_theme_path"}), 0 + }, + [ELM_SYSTRAY_SIGNAL_NEWSTATUS] = { + "NewStatus", EDBUS_ARGS({"s", "status"}), 0 + }, + [ELM_SYSTRAY_SIGNAL_NEWTITLE] = { + "NewTitle", NULL, 0 + }, + [ELM_SYSTRAY_SIGNAL_XAYATANANEWLABEL] = { + "XAyatanaNewLabel", EDBUS_ARGS({"s", "label"}, {"s", "guide"}), 0 + }, + { NULL, NULL, 0 } +}; + +// ============================================================================= +// Properties +// ============================================================================= +static Eina_Bool +_prop_str_empty_get(const EDBus_Service_Interface *iface EINA_UNUSED, + const char *propname EINA_UNUSED, + EDBus_Message_Iter *iter, + const EDBus_Message *request_msg EINA_UNUSED, + EDBus_Message **error EINA_UNUSED) +{ + edbus_message_iter_basic_append(iter, 's', ""); + + return EINA_TRUE; +} + +static Eina_Bool +_prop_attention_icon_name_get(const EDBus_Service_Interface *iface EINA_UNUSED, + const char *propname EINA_UNUSED, + EDBus_Message_Iter *iter, + const EDBus_Message *request_msg EINA_UNUSED, + EDBus_Message **error EINA_UNUSED) +{ + const char *s = _item.att_icon_name ? _item.att_icon_name : ""; + + edbus_message_iter_basic_append(iter, 's', s); + + return EINA_TRUE; +} + +static Eina_Bool +_prop_category_get(const EDBus_Service_Interface *iface EINA_UNUSED, + const char *propname EINA_UNUSED, + EDBus_Message_Iter *iter, + const EDBus_Message *request_msg EINA_UNUSED, + EDBus_Message **error EINA_UNUSED) +{ + edbus_message_iter_basic_append(iter, 's', _Elm_Systray_Cat_Str[_item.cat]); + + return EINA_TRUE; +} + +static Eina_Bool +_prop_icon_name_get(const EDBus_Service_Interface *iface EINA_UNUSED, + const char *propname EINA_UNUSED, + EDBus_Message_Iter *iter, + const EDBus_Message *request_msg EINA_UNUSED, + EDBus_Message **error EINA_UNUSED) +{ + const char *s = _item.icon_name ? _item.icon_name : ""; + + edbus_message_iter_basic_append(iter, 's', s); + + return EINA_TRUE; +} + +static Eina_Bool +_prop_icon_theme_path_get(const EDBus_Service_Interface *iface EINA_UNUSED, + const char *propname EINA_UNUSED, + EDBus_Message_Iter *iter, + const EDBus_Message *request_msg EINA_UNUSED, + EDBus_Message **error EINA_UNUSED) +{ + const char *s = _item.icon_theme_path ? _item.icon_theme_path : ""; + + edbus_message_iter_basic_append(iter, 's', s); + + return EINA_TRUE; +} + +static Eina_Bool +_prop_id_get(const EDBus_Service_Interface *iface EINA_UNUSED, + const char *propname EINA_UNUSED, + EDBus_Message_Iter *iter, + const EDBus_Message *request_msg EINA_UNUSED, + EDBus_Message **error EINA_UNUSED) +{ + const char *s = _item.id ? _item.id : ""; + + edbus_message_iter_basic_append(iter, 's', s); + + return EINA_TRUE; +} + +static Eina_Bool +_prop_menu_get(const EDBus_Service_Interface *iface EINA_UNUSED, + const char *propname EINA_UNUSED, + EDBus_Message_Iter *iter, + const EDBus_Message *request_msg EINA_UNUSED, + EDBus_Message **error EINA_UNUSED) +{ + const char *s = _item.menu ? _item.menu : "/"; + + edbus_message_iter_basic_append(iter, 'o', s); + + return EINA_TRUE; +} + +static Eina_Bool +_prop_status_get(const EDBus_Service_Interface *iface EINA_UNUSED, + const char *propname EINA_UNUSED, + EDBus_Message_Iter *iter, + const EDBus_Message *request_msg EINA_UNUSED, + EDBus_Message **error EINA_UNUSED) +{ + edbus_message_iter_basic_append(iter, 's', + _Elm_Systray_Status_Str[_item.status]); + + return EINA_TRUE; +} + +static Eina_Bool +_prop_title_get(const EDBus_Service_Interface *iface EINA_UNUSED, + const char *propname EINA_UNUSED, + EDBus_Message_Iter *iter, + const EDBus_Message *request_msg EINA_UNUSED, + EDBus_Message **error EINA_UNUSED) +{ + const char *s = _item.title ? _item.title : ""; + + edbus_message_iter_basic_append(iter, 's', s); + + return EINA_TRUE; +} + +static Eina_Bool +_prop_xayatana_orderindex_get(const EDBus_Service_Interface *iface EINA_UNUSED, + const char *propname EINA_UNUSED, + EDBus_Message_Iter *iter, + const EDBus_Message *request_msg EINA_UNUSED, + EDBus_Message **error EINA_UNUSED) +{ + edbus_message_iter_basic_append(iter, 'u', 0); + + return EINA_TRUE; +} + +static const EDBus_Property properties[] = { + { "AttentionAcessibleDesc", "s", _prop_str_empty_get, NULL, 0 }, + { "AttentionIconName", "s", _prop_attention_icon_name_get, NULL, 0 }, + { "Category", "s", _prop_category_get, NULL, 0 }, + { "IconAcessibleDesc", "s", _prop_str_empty_get, NULL, 0 }, + { "IconName", "s", _prop_icon_name_get, NULL, 0 }, + { "IconThemePath", "s", _prop_icon_theme_path_get, NULL, 0 }, + { "Id", "s", _prop_id_get, NULL, 0 }, + { "Menu", "o", _prop_menu_get, NULL, 0 }, + { "Status", "s", _prop_status_get, NULL, 0 }, + { "Title", "s", _prop_title_get, NULL, 0 }, + { "XAyatanaLabelGuide", "s", _prop_str_empty_get, NULL, 0 }, + { "XAyatanaLabel", "s", _prop_str_empty_get, NULL, 0 }, + { "XAyatanaOrderingIndex", "u", _prop_xayatana_orderindex_get, NULL, 0 }, + { NULL, NULL, NULL, NULL, 0 } +}; + +static const EDBus_Service_Interface_Desc _iface_desc = { + INTERFACE, methods, signals, properties, NULL, NULL +}; +#endif +// ============================================================================= + +static void +_menu_died(void *data EINA_UNUSED, + Evas *e EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + _item.menu_obj = NULL; + + eina_stringshare_replace(&(_item.menu), NULL); + +#ifdef ELM_EDBUS2 + edbus_service_property_changed(_iface, "Menu"); +#endif +} + +static void +_category_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + Elm_Systray_Category cat = va_arg(*args, Elm_Systray_Category); + + if (_item.cat == cat) return; + + _item.cat = cat; +#ifdef ELM_EDBUS2 + edbus_service_property_changed(_iface, "Category"); +#endif +} + +static void +_category_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + Elm_Systray_Category *ret = va_arg(*args, Elm_Systray_Category *); + + *ret = _item.cat; +} + +static void +_status_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + Elm_Systray_Status st = va_arg(*args, Elm_Systray_Status); + + if (_item.status == st) return; + + _item.status = st; +#ifdef ELM_EDBUS2 + edbus_service_property_changed(_iface, "Status"); + _elm_systray_signal_emit(ELM_SYSTRAY_SIGNAL_NEWSTATUS, + _Elm_Systray_Status_Str[_item.status]); +#endif +} + +static void +_status_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + Elm_Systray_Status *ret = va_arg(*args, Elm_Systray_Status *); + *ret = _item.status; +} + +static void +_att_icon_name_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const char *att_icon_name = va_arg(*args, const char *); + + if (!eina_stringshare_replace(&(_item.att_icon_name), att_icon_name)) return; + +#ifdef ELM_EDBUS2 + edbus_service_property_changed(_iface, "AttentionIconName"); + _elm_systray_signal_emit(ELM_SYSTRAY_SIGNAL_NEWATTENTIONICON, NULL); +#endif +} + +static void +_att_icon_name_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const char **ret = va_arg(*args, const char **); + *ret = _item.att_icon_name; +} + +static void +_icon_name_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const char *icon_name = va_arg(*args, const char *); + + if (!eina_stringshare_replace(&(_item.icon_name), icon_name)) return; + +#ifdef ELM_EDBUS2 + edbus_service_property_changed(_iface, "IconName"); + _elm_systray_signal_emit(ELM_SYSTRAY_SIGNAL_NEWICON, NULL); +#endif +} + +static void +_icon_name_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const char **ret = va_arg(*args, const char **); + *ret = _item.icon_name; +} + +static void +_icon_theme_path_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const char *icon_theme_path = va_arg(*args, const char *); + + if (!eina_stringshare_replace(&(_item.icon_theme_path), icon_theme_path)) + return; + +#ifdef ELM_EDBUS2 + edbus_service_property_changed(_iface, "IconThemePath"); + _elm_systray_signal_emit(ELM_SYSTRAY_SIGNAL_NEWICONTHEMEPATH, + _item.icon_theme_path); +#endif +} + +static void +_icon_theme_path_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const char **ret = va_arg(*args, const char **); + *ret = _item.icon_theme_path; +} + +static void +_id_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const char *id = va_arg(*args, const char *); + + if (!eina_stringshare_replace(&(_item.id), id)) return; + +#ifdef ELM_EDBUS2 + edbus_service_property_changed(_iface, "Id"); +#endif +} + +static void +_id_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const char **ret = va_arg(*args, const char **); + *ret = _item.id; +} + +static void +_title_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const char *title = va_arg(*args, const char *); + + if (!eina_stringshare_replace(&(_item.title), title)) return; + +#ifdef ELM_EDBUS2 + edbus_service_property_changed(_iface, "Title"); + _elm_systray_signal_emit(ELM_SYSTRAY_SIGNAL_NEWTITLE, NULL); +#endif +} + +static void +_title_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const char **ret = va_arg(*args, const char **); + *ret = _item.title; +} + +static void +_menu_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const Eo *menu_obj = va_arg(*args, const Eo *); + const char *menu = NULL; + + if (_item.menu_obj == menu_obj) return; + + if (menu_obj) + { + menu = _elm_dbus_menu_register((Eo *) menu_obj); + evas_object_event_callback_add((Evas_Object *) menu_obj, + EVAS_CALLBACK_DEL, _menu_died, NULL); + } + + eina_stringshare_replace(&(_item.menu), menu); + + if (_item.menu_obj) + evas_object_event_callback_del_full((Evas_Object *) _item.menu_obj, + EVAS_CALLBACK_DEL, _menu_died, NULL); + + _item.menu_obj = menu_obj; + +#ifdef ELM_EDBUS2 + edbus_service_property_changed(_iface, "Menu"); +#endif +} + +static void +_menu_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + const Eo **ret = va_arg(*args, const Eo **); + *ret = _item.menu_obj; +} + +static void +_register(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args) +{ + Eina_Bool *ret = va_arg(*args, Eina_Bool *); +#ifdef ELM_EDBUS2 + if (!_elm_need_systray) goto err; + + *ret = _elm_systray_watcher_status_notifier_item_register(OBJ_PATH); + return; + +err: +#endif + *ret = EINA_FALSE; +} + +EAPI Eina_Bool +elm_need_systray(void) +{ +#ifdef ELM_EDBUS2 + if (_elm_need_systray) return EINA_TRUE; + + if (!elm_need_edbus()) return EINA_FALSE; + + if (!ELM_EVENT_SYSTRAY_READY) + ELM_EVENT_SYSTRAY_READY = ecore_event_type_new(); + + if (!_elm_systray_watcher_init()) return EINA_FALSE; + + _conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION); + if (!_conn) goto err; + + _iface = edbus_service_interface_register(_conn, OBJ_PATH, &_iface_desc); + if (!_iface) goto err; + + _elm_need_systray = EINA_TRUE; + return EINA_TRUE; + +err: + if (_conn) + { + edbus_connection_unref(_conn); + _conn = NULL; + } + + _elm_systray_watcher_shutdown(); +#endif + return EINA_FALSE; +} + +void +_elm_unneed_systray(void) +{ +#ifdef ELM_EDBUS2 + if (!_elm_need_systray) return; + + _elm_need_systray = EINA_FALSE; + + edbus_service_interface_unregister(_iface); + + edbus_connection_unref(_conn); + + _elm_systray_watcher_shutdown(); + + eina_stringshare_del(_item.att_icon_name); + eina_stringshare_del(_item.icon_name); + eina_stringshare_del(_item.icon_theme_path); + eina_stringshare_del(_item.id); + eina_stringshare_del(_item.title); + eina_stringshare_del(_item.menu); + + if (_item.menu_obj) + { + evas_object_event_callback_del_full((Evas_Object *) _item.menu_obj, + EVAS_CALLBACK_DEL, _menu_died, + NULL); + _item.menu_obj = NULL; + } +#endif +} + +// ============================================================================= +// EObject Stuff +// ============================================================================= +static void +_class_constructor(Eo_Class *klass) +{ + const Eo_Op_Func_Description func_desc[] = { + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_SET), + _category_set), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_GET), + _category_get), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_SET), + _status_set), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_GET), + _status_get), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_SET), + _att_icon_name_set), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_GET), + _att_icon_name_get), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_SET), + _icon_name_set), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_GET), + _icon_name_get), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_SET), + _icon_theme_path_set), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_GET), + _icon_theme_path_get), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ID_SET), + _id_set), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ID_GET), + _id_get), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_SET), + _title_set), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_GET), + _title_get), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_MENU_SET), + _menu_set), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_MENU_GET), + _menu_get), + EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_REGISTER), + _register), + EO_OP_FUNC_SENTINEL + }; + eo_class_funcs_set(klass, func_desc); +} + +static const Eo_Op_Description op_desc[] = { + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_SET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_GET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_SET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_GET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_SET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_GET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_SET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_GET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_SET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_GET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ID_SET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ID_GET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_SET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_GET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_MENU_SET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_MENU_GET, ""), + EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_REGISTER, ""), + EO_OP_DESCRIPTION_SENTINEL +}; + +static const Eo_Class_Description class_desc = { + EO_VERSION, + "elm_systray", + EO_CLASS_TYPE_REGULAR, + EO_CLASS_DESCRIPTION_OPS + (&ELM_OBJ_SYSTRAY_BASE_ID, op_desc, ELM_OBJ_SYSTRAY_SUB_ID_LAST), + NULL, + 0, + _class_constructor, + NULL//_class_destructor, +}; + +EO_DEFINE_CLASS(elm_obj_systray_class_get, &class_desc, EO_BASE_CLASS, NULL); diff --git a/legacy/elementary/src/lib/elm_systray.h b/legacy/elementary/src/lib/elm_systray.h new file mode 100644 index 0000000000..225daa773d --- /dev/null +++ b/legacy/elementary/src/lib/elm_systray.h @@ -0,0 +1,324 @@ +#ifndef ELM_SYSTRAY_H +#define ELM_SYSTRAY_H + +#include "Eo.h" + +#define ELM_OBJ_SYSTRAY_CLASS elm_obj_systray_class_get() + +const Eo_Class *elm_obj_systray_class_get(void) EINA_CONST; + +extern EAPI Eo_Op ELM_OBJ_SYSTRAY_BASE_ID; + +enum +{ + ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_SET, + ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_GET, + ELM_OBJ_SYSTRAY_SUB_ID_STATUS_SET, + ELM_OBJ_SYSTRAY_SUB_ID_STATUS_GET, + ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_SET, + ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_GET, + ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_SET, + ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_GET, + ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_SET, + ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_GET, + ELM_OBJ_SYSTRAY_SUB_ID_ID_SET, + ELM_OBJ_SYSTRAY_SUB_ID_ID_GET, + ELM_OBJ_SYSTRAY_SUB_ID_TITLE_SET, + ELM_OBJ_SYSTRAY_SUB_ID_TITLE_GET, + ELM_OBJ_SYSTRAY_SUB_ID_MENU_SET, + ELM_OBJ_SYSTRAY_SUB_ID_MENU_GET, + ELM_OBJ_SYSTRAY_SUB_ID_REGISTER, + ELM_OBJ_SYSTRAY_SUB_ID_LAST +}; + +#define ELM_OBJ_SYSTRAY_ID(sub_id) (ELM_OBJ_SYSTRAY_BASE_ID + sub_id) + +/** + * @def elm_obj_systray_category_set + * + * Set the category of the Status Notifier Item. + * + * @param[in] cat Category + * + * @see Elm_Systray_Category + * + * @since 1.8 + */ +#define elm_obj_systray_category_set(cat) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_SET), \ + EO_TYPECHECK(Elm_Systray_Category, cat) + +/** + * @def elm_obj_systray_category_get + * + * Retrieve the category of the Status Notifier Item. + * + * @param[out] ret Category + * + * @see elm_obj_systray_category_set + * + * @since 1.8 + */ +#define elm_obj_systray_category_get(ret) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_GET), \ + EO_TYPECHECK(Elm_Systray_Category *, ret) + +/** + * @def elm_obj_systray_status_set + * + * Set the status of the Status Notifier Item. + * + * @param[in] st Status + * + * @see Elm_Systray_Status + * + * @since 1.8 + */ +#define elm_obj_systray_status_set(st) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_SET), \ + EO_TYPECHECK(Elm_Systray_Status, st) + +/** + * @def elm_obj_systray_status_get + * + * Retrieve the status of the Status Notifier Item. + * + * @param[out] ret Status + * + * @see elm_obj_systray_status_set + * + * @since 1.8 + */ +#define elm_obj_systray_status_get(ret) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_GET), \ + EO_TYPECHECK(Elm_Systray_Status *, ret) + +/** + * @def elm_obj_systray_att_icon_name_set + * + * Set the name of the attention icon to be used by the Status Notifier Item. + * + * @param[in] att_icon_name + * + * @see elm_obj_systray_att_icon_name_get + * + * @since 1.8 + */ +#define elm_obj_systray_att_icon_name_set(att_icon_name) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_SET), \ + EO_TYPECHECK(const char *, att_icon_name) + +/** + * @def elm_obj_systray_att_icon_name_get + * + * Retrieve the name of the attention icon used by the Status Notifier Item. + * + * @param[out] ret + * + * @see elm_obj_systray_att_icon_name_set + * + * @since 1.8 + */ +#define elm_obj_systray_att_icon_name_get(ret) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_GET), \ + EO_TYPECHECK(const char **, ret) + +/** + * @def elm_obj_systray_icon_name_set + * + * Set the name of the icon to be used by the Status Notifier Item. + * + * @param[in] icon_name + * + * @see elm_obj_systray_icon_name_get + * + * @since 1.8 + */ +#define elm_obj_systray_icon_name_set(icon_name) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_SET), \ + EO_TYPECHECK(const char *, icon_name) + +/** + * @def elm_obj_systray_icon_name_get + * + * Retrieve the name of the icon used by the Status Notifier Item. + * + * @param[out] ret + * + * @see elm_obj_systray_icon_name_set + * + * @since 1.8 + */ +#define elm_obj_systray_icon_name_get(ret) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_GET), \ + EO_TYPECHECK(const char **, ret) + +/** + * @def elm_obj_systray_icon_theme_path_set + * + * Set the path to the theme where the icons can be found. + * Set this value to "" to use the default path. + * + * @param[in] icon_theme_path + * + * @see elm_obj_systray_icon_theme_path_get + * + * @since 1.8 + */ +#define elm_obj_systray_icon_theme_path_set(icon_theme_path) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_SET), \ + EO_TYPECHECK(const char *, icon_theme_path) + +/** + * @def elm_obj_systray_icon_theme_path_get + * + * Retrieve the path to the icon's theme currently in use. + * + * @param[out] ret + * + * @see elm_obj_systray_icon_theme_path_set + * + * @since 1.8 + */ +#define elm_obj_systray_icon_theme_path_get(ret) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_GET), \ + EO_TYPECHECK(const char **, ret) + +/** + * @def elm_obj_systray_id_set + * + * Set the id of the Status Notifier Item. + * + * @param[in] id + * + * @see elm_obj_systray_id_get + * + * @since 1.8 + */ +#define elm_obj_systray_id_set(id) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ID_SET), \ + EO_TYPECHECK(const char *, id) + +/** + * @def elm_obj_systray_id_get + * + * Retrieve the id of the Status Notifier Item. + * + * @param[out] ret + * + * @see elm_obj_systray_id_set + * + * @since 1.8 + */ +#define elm_obj_systray_id_get(ret) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ID_GET), \ + EO_TYPECHECK(const char **, ret) + +/** + * @def elm_obj_systray_title_set + * + * Set the title of the Status Notifier Item. + * + * @param[in] title + * + * @see elm_obj_systray_title_get + * + * @since 1.8 + */ +#define elm_obj_systray_title_set(title) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_SET), \ + EO_TYPECHECK(const char *, title) + +/** + * @def elm_obj_systray_title_get + * + * Retrieve the title of the Status Notifier Item. + * + * @param[out] ret + * + * @see elm_obj_systray_title_set + * + * @since 1.8 + */ +#define elm_obj_systray_title_get(ret) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_GET), \ + EO_TYPECHECK(const char **, ret) + +/** + * @def elm_obj_systray_menu_set + * + * Set the object path of the D-Bus Menu that is to be show when the + * Status Notifier Item is activated by the user. + * + * @param[in] menu + * + * @see elm_obj_systray_menu_get + * + * @since 1.8 + */ +#define elm_obj_systray_menu_set(menu) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_MENU_SET), \ + EO_TYPECHECK(const Eo *, menu) + +/** + * @def elm_obj_systray_menu_get + * + * Retrieve the object path of the D-Bus Menu currently in use. + * + * @param[out] ret + * + * @see elm_obj_systray_menu_set + * + * @since 1.8 + */ +#define elm_obj_systray_menu_get(ret) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_MENU_GET), \ + EO_TYPECHECK(const Eo **, ret) + +/** + * @def elm_obj_systray_register + * + * Register this Status Notifier Item in the System Tray Watcher. + * This function should only be called after the event + * ELM_EVENT_SYSTRAY_READY is emitted. + * + * @param[out] ret + * + * @since 1.8 + */ +#define elm_obj_systray_register(ret) \ + ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_REGISTER), \ + EO_TYPECHECK(Eina_Bool *, ret) + +/** + * Emitted when the systray is ready to be used by the application. + */ +EAPI extern int ELM_EVENT_SYSTRAY_READY; + +/** + * Category of the Status Notifier Item. + * + * @since 1.8 + */ +typedef enum _Elm_Systray_Category +{ + ELM_SYSTRAY_CATEGORY_APP_STATUS, /**< Indicators of application status */ + ELM_SYSTRAY_CATEGORY_COMMUNICATIONS, /**< Communications apps */ + ELM_SYSTRAY_CATEGORY_SYS_SERVICES, /**< System Service apps */ + ELM_SYSTRAY_CATEGORY_HARDWARE, /**< Hardware indicators */ + ELM_SYSTRAY_CATEGORY_OTHER /**< Undefined category */ +} Elm_Systray_Category; + +/** + * Application status information. + * + * @since 1.8 + */ +typedef enum _Elm_Systray_Status +{ + ELM_SYSTRAY_STATUS_PASSIVE, /**< Passive (normal) */ + ELM_SYSTRAY_STATUS_ACTIVE, /**< Active */ + ELM_SYSTRAY_STATUS_ATTENTION /**< Needs Attention */ +} Elm_Systray_Status; + +#endif diff --git a/legacy/elementary/src/lib/elm_systray_watcher.c b/legacy/elementary/src/lib/elm_systray_watcher.c new file mode 100644 index 0000000000..196381ec9b --- /dev/null +++ b/legacy/elementary/src/lib/elm_systray_watcher.c @@ -0,0 +1,126 @@ +#include "Elementary.h" +#include "elm_priv.h" + +#include "elm_systray_watcher.h" + +#ifdef ELM_EDBUS2 +#define OBJ "/StatusNotifierWatcher" +#define BUS "org.kde.StatusNotifierWatcher" +#define INTERFACE "org.kde.StatusNotifierWatcher" + +static Eina_Bool _elm_systray_watcher = EINA_FALSE; + +static EDBus_Connection *_watcher_conn = NULL; +static EDBus_Object *_watcher_obj = NULL; +static EDBus_Proxy *_watcher_proxy = NULL; + +static void +_status_notifier_item_register_cb(void *data EINA_UNUSED, + const EDBus_Message *msg, + EDBus_Pending *pending EINA_UNUSED) +{ + const char *errname, *errmsg; + + if (edbus_message_error_get(msg, &errname, &errmsg)) + ERR("Edbus Error: %s %s", errname, errmsg); +} +#endif + +Eina_Bool +_elm_systray_watcher_status_notifier_item_register(const char *obj) +{ +#ifdef ELM_EDBUS2 + EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(_watcher_proxy, EINA_FALSE); + + if (!edbus_proxy_call(_watcher_proxy, "RegisterStatusNotifierItem", + _status_notifier_item_register_cb, + NULL, -1, "s", obj)) + { + ERR("Error sending message: "INTERFACE".RegisterStatusNotifierItem."); + return EINA_FALSE; + } + + return EINA_TRUE; +#else + (void) obj; + return EINA_FALSE; +#endif +} + +#ifdef ELM_EDBUS2 +static void +_release(void) +{ + if (_watcher_proxy) + { + edbus_proxy_unref(_watcher_proxy); + _watcher_proxy = NULL; + } + + if (_watcher_obj) + { + edbus_object_unref(_watcher_obj); + _watcher_obj = NULL; + } +} + +static void +_update(void) +{ + _release(); + + _watcher_obj = edbus_object_get(_watcher_conn, BUS, OBJ); + _watcher_proxy = edbus_proxy_get(_watcher_obj, INTERFACE); + + ecore_event_add(ELM_EVENT_SYSTRAY_READY, NULL, NULL, NULL); +} + +static void +_name_owner_changed_cb(void *data EINA_UNUSED, + const char *bus EINA_UNUSED, + const char *old_id EINA_UNUSED, + const char *new_id) +{ + if ((!new_id) || (*new_id == '\0')) + _release(); + else + _update(); +} +#endif + +Eina_Bool +_elm_systray_watcher_init(void) +{ +#ifdef ELM_EDBUS2 + if (_elm_systray_watcher) return EINA_TRUE; + + if (!elm_need_edbus()) return EINA_FALSE; + + _watcher_conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION); + + edbus_name_owner_changed_callback_add(_watcher_conn, BUS, + _name_owner_changed_cb, NULL, + EINA_TRUE); + + _elm_systray_watcher = EINA_TRUE; + return EINA_TRUE; +#else + return EINA_FALSE; +#endif +} + +void +_elm_systray_watcher_shutdown(void) +{ +#ifdef ELM_EDBUS2 + if (!_elm_systray_watcher) return; + + _elm_systray_watcher = EINA_FALSE; + + _release(); + + edbus_connection_unref(_watcher_conn); + _watcher_conn = NULL; +#endif +} diff --git a/legacy/elementary/src/lib/elm_systray_watcher.h b/legacy/elementary/src/lib/elm_systray_watcher.h new file mode 100644 index 0000000000..337cce6d77 --- /dev/null +++ b/legacy/elementary/src/lib/elm_systray_watcher.h @@ -0,0 +1,10 @@ +#ifndef ELM_SYSTRAY_WATCHER_H +#define ELM_SYSTRAY_WATCHER_H + +Eina_Bool _elm_systray_watcher_status_notifier_item_register(const char *obj); + +Eina_Bool _elm_systray_watcher_init(void); + +void _elm_systray_watcher_shutdown(void); + +#endif