summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--NEWS1
-rw-r--r--src/bin/Makefile.am1
-rw-r--r--src/bin/test.c2
-rw-r--r--src/bin/test_systray.c194
-rw-r--r--src/lib/Elementary.h.in1
-rw-r--r--src/lib/Makefile.am4
-rw-r--r--src/lib/elm_main.c1
-rw-r--r--src/lib/elm_need.h14
-rw-r--r--src/lib/elm_priv.h1
-rw-r--r--src/lib/elm_systray.c650
-rw-r--r--src/lib/elm_systray.h324
-rw-r--r--src/lib/elm_systray_watcher.c126
-rw-r--r--src/lib/elm_systray_watcher.h10
14 files changed, 1333 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 49553afc5..ae893bbe1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -845,3 +845,7 @@
845 * Add elm_dbus_menu to support D-Bus external menus. 845 * Add elm_dbus_menu to support D-Bus external menus.
846 * Add main menu to elm_win, which can be exported via D-Bus 846 * Add main menu to elm_win, which can be exported via D-Bus
847 * Add configuration: ELM_EXTERNAL_MENU, to switch between internal and external menus 847 * Add configuration: ELM_EXTERNAL_MENU, to switch between internal and external menus
848
8492012-12-20 Murilo Pinoti Belluzzo (mbelluzzo)
850
851 * Add elm_systray to set a Status Notifier Item in the System Tray (D-Bus).
diff --git a/NEWS b/NEWS
index 9a4c6f1ae..cd1a4b3db 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,7 @@ Additions:
25 * Add elm_plug signals "image,deleted" (fixed typo) and "image,resized". 25 * Add elm_plug signals "image,deleted" (fixed typo) and "image,resized".
26 * Add elm_dbus_menu to support D-Bus external menus. 26 * Add elm_dbus_menu to support D-Bus external menus.
27 * Add configuration: ELM_EXTERNAL_MENU, to switch between internal and extenal menus 27 * Add configuration: ELM_EXTERNAL_MENU, to switch between internal and extenal menus
28 * Add elm_systray.[ch]: Add support to D-Bus systray icons.
28 29
29Improvements: 30Improvements:
30 31
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
index 657c6472e..12bf6efaf 100644
--- a/src/bin/Makefile.am
+++ b/src/bin/Makefile.am
@@ -124,6 +124,7 @@ test_slideshow.c \
124test_spinner.c \ 124test_spinner.c \
125test_store.c \ 125test_store.c \
126test_sys_notify.c \ 126test_sys_notify.c \
127test_systray.c \
127test_table.c \ 128test_table.c \
128test_thumb.c \ 129test_thumb.c \
129test_toolbar.c \ 130test_toolbar.c \
diff --git a/src/bin/test.c b/src/bin/test.c
index e571fea91..c491897b9 100644
--- a/src/bin/test.c
+++ b/src/bin/test.c
@@ -178,6 +178,7 @@ void test_bubble(void *data, Evas_Object *obj, void *event_info);
178void test_segment_control(void *data, Evas_Object *obj, void *event_info); 178void test_segment_control(void *data, Evas_Object *obj, void *event_info);
179void test_store(void *data, Evas_Object *obj, void *event_info); 179void test_store(void *data, Evas_Object *obj, void *event_info);
180void test_sys_notify(void *data, Evas_Object *obj, void *event_info); 180void test_sys_notify(void *data, Evas_Object *obj, void *event_info);
181void test_systray(void *data, Evas_Object *obj, void *event_info);
181void test_win_inline(void *data, Evas_Object *obj, void *event_info); 182void test_win_inline(void *data, Evas_Object *obj, void *event_info);
182void test_win_socket(void *data, Evas_Object *obj, void *event_info); 183void test_win_socket(void *data, Evas_Object *obj, void *event_info);
183void test_win_plug(void *data, Evas_Object *obj, void *event_info); 184void test_win_plug(void *data, Evas_Object *obj, void *event_info);
@@ -727,6 +728,7 @@ add_tests:
727 728
728 //------------------------------// 729 //------------------------------//
729 ADD_TEST(NULL, "System", "Notification", test_sys_notify); 730 ADD_TEST(NULL, "System", "Notification", test_sys_notify);
731 ADD_TEST(NULL, "System", "Systray Item", test_systray);
730 732
731 //------------------------------// 733 //------------------------------//
732 ADD_TEST(NULL, "Micellaneous", "Copy And Paste", test_cnp); 734 ADD_TEST(NULL, "Micellaneous", "Copy And Paste", test_cnp);
diff --git a/src/bin/test_systray.c b/src/bin/test_systray.c
new file mode 100644
index 000000000..864c58f28
--- /dev/null
+++ b/src/bin/test_systray.c
@@ -0,0 +1,194 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4#include <Elementary.h>
5#ifndef ELM_LIB_QUICKLAUNCH
6
7#define WIDTH 320
8#define HEIGHT 160
9
10static Evas_Object *ai = NULL;
11static Evas_Object *i = NULL;
12static Evas_Object *r = NULL;
13static Eo *item = NULL;
14
15static Eina_Bool
16_ev_handler(void *data __UNUSED__,
17 int type __UNUSED__,
18 void *event __UNUSED__)
19{
20 Eina_Bool ret;
21
22 printf("systray ready event\n");
23
24 eo_do(item, elm_obj_systray_register(&ret));
25
26 printf("Item Registration: ");
27 if (ret)
28 printf("OK!\n");
29 else
30 printf("Failed!\n");
31
32 return ECORE_CALLBACK_DONE;
33}
34
35static void
36_bt_clicked(void *data __UNUSED__,
37 Evas_Object *obj __UNUSED__,
38 void *event_info __UNUSED__)
39{
40 eo_do(item, elm_obj_systray_icon_name_set(elm_entry_entry_get(i)));
41 eo_do(item, elm_obj_systray_att_icon_name_set(elm_entry_entry_get(ai)));
42}
43
44static void
45 _r_clicked(void *data __UNUSED__,
46 Evas_Object *obj __UNUSED__,
47 void *event_info __UNUSED__)
48{
49 eo_do(item, elm_obj_systray_status_set(elm_radio_value_get(r)));
50}
51
52static void
53_menu_clicked(void *data,
54 Evas_Object *obj __UNUSED__,
55 void *event_info __UNUSED__)
56{
57 printf("Menu Item Clicked: %s\n", (const char *) data);
58}
59
60void
61test_systray(void *data __UNUSED__,
62 Evas_Object *obj __UNUSED__,
63 void *event_info __UNUSED__)
64{
65 Evas_Object *win, *bx, *it;
66 Elm_Object_Item *it2;
67 int st = 1;
68
69 Eina_Bool init_ok = elm_need_systray();
70
71 ecore_event_handler_add(ELM_EVENT_SYSTRAY_READY,
72 _ev_handler, NULL);
73
74 win = elm_win_add(NULL, "Systray", ELM_WIN_BASIC);
75 elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
76 elm_win_title_set(win, "Systemtray - Status Notifier Item");
77 elm_win_autodel_set(win, EINA_TRUE);
78
79 it = elm_menu_add(win);
80 elm_menu_item_add(it, NULL, NULL, "root 1", _menu_clicked, "root 1");
81 it2 = elm_menu_item_add(it, NULL, NULL, "root 2", _menu_clicked, "root 2");
82 elm_menu_item_add(it, it2, NULL, "item 1", _menu_clicked, "item 1");
83 elm_menu_item_add(it, it2, NULL, "item 2", _menu_clicked, "item 2");
84
85 // Status Notifier Item Handler
86 item = eo_add(ELM_OBJ_SYSTRAY_CLASS, win);
87 eo_do(item, elm_obj_systray_icon_name_set("elementary"));
88 eo_do(item, elm_obj_systray_att_icon_name_set("elementary"));
89 eo_do(item, elm_obj_systray_menu_set(it));
90
91 it = elm_bg_add(win);
92 elm_win_resize_object_add(win, it);
93 evas_object_size_hint_min_set(it, WIDTH, HEIGHT);
94 evas_object_size_hint_max_set(it, WIDTH, HEIGHT);
95 evas_object_show(it);
96
97 bx = elm_box_add(win);
98 evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
99 elm_win_resize_object_add(win, bx);
100 evas_object_show(bx);
101
102 if (!init_ok)
103 {
104 it = elm_label_add(win);
105 evas_object_size_hint_align_set(it, 0, EVAS_HINT_FILL);
106 elm_object_text_set(it, "Systray initialization failed. "
107 "This test will do nothing.");
108 elm_box_pack_end(bx, it);
109 evas_object_show(it);
110 }
111
112 it = elm_label_add(win);
113 evas_object_size_hint_align_set(it, 0, EVAS_HINT_FILL);
114 elm_object_text_set(it, "Icon:");
115 elm_box_pack_end(bx, it);
116 evas_object_show(it);
117
118 i = elm_entry_add(win);
119 elm_entry_single_line_set(i, EINA_TRUE);
120 elm_entry_scrollable_set(i, EINA_TRUE);
121 elm_entry_entry_set(i, "elementary");
122 evas_object_size_hint_align_set(i, EVAS_HINT_FILL, EVAS_HINT_FILL);
123 elm_box_pack_end(bx, i);
124 evas_object_show(i);
125
126 it = elm_label_add(win);
127 evas_object_size_hint_align_set(it, 0, EVAS_HINT_FILL);
128 elm_object_text_set(it, "Attention Icon:");
129 elm_box_pack_end(bx, it);
130 evas_object_show(it);
131
132 ai = elm_entry_add(win);
133 elm_entry_single_line_set(ai, EINA_TRUE);
134 elm_entry_scrollable_set(ai, EINA_TRUE);
135 elm_entry_entry_set(ai, "elementary");
136 evas_object_size_hint_align_set(ai, EVAS_HINT_FILL, EVAS_HINT_FILL);
137 elm_box_pack_end(bx, ai);
138 evas_object_show(ai);
139
140 it = elm_button_add(win);
141 elm_object_text_set(it, "Update");
142 evas_object_smart_callback_add(it, "clicked", _bt_clicked, NULL);
143 elm_box_pack_end(bx, it);
144 evas_object_show(it);
145
146 it = elm_separator_add(win);
147 elm_separator_horizontal_set(it, EINA_TRUE);
148 elm_box_pack_end(bx, it);
149 evas_object_show(it);
150
151 it = elm_label_add(win);
152 evas_object_size_hint_align_set(it, EVAS_HINT_FILL, EVAS_HINT_FILL);
153 elm_object_text_set(it, "Status:");
154 elm_box_pack_end(bx, it);
155 evas_object_show(it);
156
157 it = elm_box_add(win);
158 elm_box_horizontal_set(it, EINA_TRUE);
159 elm_box_homogeneous_set(it, EINA_TRUE);
160 elm_box_pack_end(bx, it);
161 evas_object_show(it);
162 bx = it;
163
164 r = elm_radio_add(win);
165 evas_object_size_hint_align_set(r, EVAS_HINT_FILL, EVAS_HINT_FILL);
166 evas_object_smart_callback_add(r, "changed", _r_clicked, NULL);
167 elm_radio_value_pointer_set(r, &st);
168 elm_radio_state_value_set(r, 0);
169 elm_object_text_set(r, "Passive");
170 elm_box_pack_end(bx, r);
171 evas_object_show(r);
172
173 it = elm_radio_add(win);
174 evas_object_size_hint_align_set(it, EVAS_HINT_FILL, EVAS_HINT_FILL);
175 evas_object_smart_callback_add(it, "changed", _r_clicked, NULL);
176 elm_radio_state_value_set(it, 1);
177 elm_radio_group_add(it, r);
178 elm_object_text_set(it, "Active");
179 elm_box_pack_end(bx, it);
180 evas_object_show(it);
181
182 it = elm_radio_add(win);
183 evas_object_size_hint_align_set(it, EVAS_HINT_FILL, EVAS_HINT_FILL);
184 evas_object_smart_callback_add(it, "changed", _r_clicked, NULL);
185 elm_radio_state_value_set(it, 2);
186 elm_radio_group_add(it, r);
187 elm_object_text_set(it, "Needs Attention");
188 elm_box_pack_end(bx, it);
189 evas_object_show(it);
190
191 evas_object_resize(win, WIDTH, HEIGHT);
192 evas_object_show(win);
193}
194#endif
diff --git a/src/lib/Elementary.h.in b/src/lib/Elementary.h.in
index 8787551dd..04b7b0bc8 100644
--- a/src/lib/Elementary.h.in
+++ b/src/lib/Elementary.h.in
@@ -163,6 +163,7 @@ EAPI extern Elm_Version *elm_version;
163 163
164#include <elm_prefs_data.h> 164#include <elm_prefs_data.h>
165#include <elm_prefs.h> 165#include <elm_prefs.h>
166#include <elm_systray.h>
166#include <elm_sys_notify.h> 167#include <elm_sys_notify.h>
167 168
168/* special widgets - types used elsewhere */ 169/* special widgets - types used elsewhere */
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index b984aa499..83205f00d 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -195,6 +195,8 @@ elm_slider.h \
195elm_slideshow.h \ 195elm_slideshow.h \
196elm_spinner.h \ 196elm_spinner.h \
197elm_store.h \ 197elm_store.h \
198elm_systray.h \
199elm_systray_watcher.h \
198elm_sys_notify.h \ 200elm_sys_notify.h \
199elm_table.h \ 201elm_table.h \
200elm_theme.h \ 202elm_theme.h \
@@ -283,6 +285,8 @@ elm_slider.c \
283elm_slideshow.c \ 285elm_slideshow.c \
284elm_spinner.c \ 286elm_spinner.c \
285elm_store.c \ 287elm_store.c \
288elm_systray.c \
289elm_systray_watcher.c \
286elm_sys_notify.c \ 290elm_sys_notify.c \
287elm_table.c \ 291elm_table.c \
288elm_theme.c \ 292elm_theme.c \
diff --git a/src/lib/elm_main.c b/src/lib/elm_main.c
index 5526e0639..1bfa5cde2 100644
--- a/src/lib/elm_main.c
+++ b/src/lib/elm_main.c
@@ -649,6 +649,7 @@ elm_quicklaunch_shutdown(void)
649 _elm_exit_handler = NULL; 649 _elm_exit_handler = NULL;
650 650
651 _elm_theme_shutdown(); 651 _elm_theme_shutdown();
652 _elm_unneed_systray();
652 _elm_unneed_sys_notify(); 653 _elm_unneed_sys_notify();
653 _elm_unneed_efreet(); 654 _elm_unneed_efreet();
654 _elm_unneed_e_dbus(); 655 _elm_unneed_e_dbus();
diff --git a/src/lib/elm_need.h b/src/lib/elm_need.h
index f488575ca..4a4532b46 100644
--- a/src/lib/elm_need.h
+++ b/src/lib/elm_need.h
@@ -12,6 +12,20 @@
12EAPI Eina_Bool elm_need_efreet(void); 12EAPI Eina_Bool elm_need_efreet(void);
13 13
14/** 14/**
15 * Request that your elementary application needs Elm_Systray
16 *
17 * This initializes the Elm_Systray when called and, if support exists,
18 * returns EINA_TRUE, otherwise returns EINA_FALSE. This must be called
19 * before any elm_systray calls.
20 *
21 * @return EINA_TRUE if support exists and initialization succeeded.
22 *
23 * @ingroup Elm_Systray
24 * @since 1.8
25 */
26EAPI Eina_Bool elm_need_systray(void);
27
28/**
15 * Request that your elementary application needs Elm_Sys_Notify 29 * Request that your elementary application needs Elm_Sys_Notify
16 * 30 *
17 * This initializes the Elm_Sys_Notify when called and if support exists 31 * This initializes the Elm_Sys_Notify when called and if support exists
diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h
index acd13a575..25f16d7b7 100644
--- a/src/lib/elm_priv.h
+++ b/src/lib/elm_priv.h
@@ -328,6 +328,7 @@ void _elm_widget_top_win_focused_set(Evas_Object *obj,
328 Eina_Bool top_win_focused); 328 Eina_Bool top_win_focused);
329Eina_Bool _elm_widget_top_win_focused_get(const Evas_Object *obj); 329Eina_Bool _elm_widget_top_win_focused_get(const Evas_Object *obj);
330 330
331void _elm_unneed_systray(void);
331void _elm_unneed_sys_notify(void); 332void _elm_unneed_sys_notify(void);
332void _elm_unneed_ethumb(void); 333void _elm_unneed_ethumb(void);
333void _elm_unneed_web(void); 334void _elm_unneed_web(void);
diff --git a/src/lib/elm_systray.c b/src/lib/elm_systray.c
new file mode 100644
index 000000000..321b94734
--- /dev/null
+++ b/src/lib/elm_systray.c
@@ -0,0 +1,650 @@
1#include "Elementary.h"
2#include "elm_priv.h"
3
4#include "Eo.h"
5
6EAPI Eo_Op ELM_OBJ_SYSTRAY_BASE_ID = EO_NOOP;
7
8#include "elm_systray_watcher.h"
9
10EAPI int ELM_EVENT_SYSTRAY_READY = 0;
11
12typedef struct _Elm_Systray_Private_Data
13{
14 Elm_Systray_Category cat;
15 Elm_Systray_Status status;
16
17 const char *att_icon_name;
18 const char *icon_name;
19 const char *icon_theme_path;
20 const char *id;
21 const char *title;
22 const char *menu;
23 const Eo *menu_obj;
24} Elm_Systray_Private_Data;
25
26static Elm_Systray_Private_Data _item = {
27 .cat = ELM_SYSTRAY_CATEGORY_APP_STATUS,
28 .status = ELM_SYSTRAY_STATUS_ACTIVE,
29 .att_icon_name = NULL,
30 .icon_name = NULL,
31 .icon_theme_path = NULL,
32 .id = NULL,
33 .title = NULL,
34 .menu = NULL,
35 .menu_obj = NULL
36};
37
38#ifdef ELM_EDBUS2
39
40#define OBJ_PATH "/org/ayatana/NotificationItem/StatusNotifierItem"
41#define INTERFACE "org.kde.StatusNotifierItem"
42
43static Eina_Bool _elm_need_systray = EINA_FALSE;
44
45static EDBus_Connection *_conn = NULL;
46static EDBus_Service_Interface *_iface = NULL;
47
48static const char *_Elm_Systray_Cat_Str[] = {
49 [ELM_SYSTRAY_CATEGORY_APP_STATUS] = "ApplicationStatus",
50 [ELM_SYSTRAY_CATEGORY_COMMUNICATIONS] = "Communications",
51 [ELM_SYSTRAY_CATEGORY_SYS_SERVICES] = "SystemServices",
52 [ELM_SYSTRAY_CATEGORY_HARDWARE] = "Hardware",
53 [ELM_SYSTRAY_CATEGORY_OTHER] = "Other"
54};
55
56static const char *_Elm_Systray_Status_Str[] = {
57 [ELM_SYSTRAY_STATUS_ACTIVE] = "Active",
58 [ELM_SYSTRAY_STATUS_PASSIVE] = "Passive",
59 [ELM_SYSTRAY_STATUS_ATTENTION] = "NeedsAttention"
60};
61
62// =============================================================================
63// org.kde.StatusNotifierItem Service
64// =============================================================================
65// =============================================================================
66// Methods
67// =============================================================================
68static EDBus_Message *
69_empty_method(const EDBus_Service_Interface *iface EINA_UNUSED,
70 const EDBus_Message *msg)
71{
72 return edbus_message_method_return_new(msg);
73}
74
75static const EDBus_Method methods[] = {
76 {
77 "Scroll",
78 EDBUS_ARGS({"i", "delta"}, {"s", "orientation"}),
79 NULL,
80 _empty_method,
81 0
82 },
83 {
84 "SecondaryActivate",
85 EDBUS_ARGS({"i", "x"}, {"i", "y"}),
86 NULL,
87 _empty_method,
88 0
89 },
90 {
91 "XAyatanaSecondaryActivate",
92 EDBUS_ARGS({"u", "timestamp"}),
93 NULL,
94 _empty_method,
95 0
96 },
97 { NULL, NULL, NULL, NULL, 0 }
98};
99
100// =============================================================================
101// Signals
102// =============================================================================
103typedef enum _Elm_Systray_Service_Signals
104{
105 ELM_SYSTRAY_SIGNAL_NEWATTENTIONICON,
106 ELM_SYSTRAY_SIGNAL_NEWICON,
107 ELM_SYSTRAY_SIGNAL_NEWICONTHEMEPATH,
108 ELM_SYSTRAY_SIGNAL_NEWSTATUS,
109 ELM_SYSTRAY_SIGNAL_NEWTITLE,
110 ELM_SYSTRAY_SIGNAL_XAYATANANEWLABEL
111} Elm_Systray_Service_Signals;
112
113#define _elm_systray_signal_emit(sig, ...) \
114 edbus_service_signal_emit(_iface, sig, __VA_ARGS__)
115
116static const EDBus_Signal signals[] = {
117 [ELM_SYSTRAY_SIGNAL_NEWATTENTIONICON] = {
118 "NewAttentionIcon", NULL, 0
119 },
120 [ELM_SYSTRAY_SIGNAL_NEWICON] = {
121 "NewIcon", NULL, 0
122 },
123 [ELM_SYSTRAY_SIGNAL_NEWICONTHEMEPATH] = {
124 "NewIconThemePath", EDBUS_ARGS({"s", "icon_theme_path"}), 0
125 },
126 [ELM_SYSTRAY_SIGNAL_NEWSTATUS] = {
127 "NewStatus", EDBUS_ARGS({"s", "status"}), 0
128 },
129 [ELM_SYSTRAY_SIGNAL_NEWTITLE] = {
130 "NewTitle", NULL, 0
131 },
132 [ELM_SYSTRAY_SIGNAL_XAYATANANEWLABEL] = {
133 "XAyatanaNewLabel", EDBUS_ARGS({"s", "label"}, {"s", "guide"}), 0
134 },
135 { NULL, NULL, 0 }
136};
137
138// =============================================================================
139// Properties
140// =============================================================================
141static Eina_Bool
142_prop_str_empty_get(const EDBus_Service_Interface *iface EINA_UNUSED,
143 const char *propname EINA_UNUSED,
144 EDBus_Message_Iter *iter,
145 const EDBus_Message *request_msg EINA_UNUSED,
146 EDBus_Message **error EINA_UNUSED)
147{
148 edbus_message_iter_basic_append(iter, 's', "");
149
150 return EINA_TRUE;
151}
152
153static Eina_Bool
154_prop_attention_icon_name_get(const EDBus_Service_Interface *iface EINA_UNUSED,
155 const char *propname EINA_UNUSED,
156 EDBus_Message_Iter *iter,
157 const EDBus_Message *request_msg EINA_UNUSED,
158 EDBus_Message **error EINA_UNUSED)
159{
160 const char *s = _item.att_icon_name ? _item.att_icon_name : "";
161
162 edbus_message_iter_basic_append(iter, 's', s);
163
164 return EINA_TRUE;
165}
166
167static Eina_Bool
168_prop_category_get(const EDBus_Service_Interface *iface EINA_UNUSED,
169 const char *propname EINA_UNUSED,
170 EDBus_Message_Iter *iter,
171 const EDBus_Message *request_msg EINA_UNUSED,
172 EDBus_Message **error EINA_UNUSED)
173{
174 edbus_message_iter_basic_append(iter, 's', _Elm_Systray_Cat_Str[_item.cat]);
175
176 return EINA_TRUE;
177}
178
179static Eina_Bool
180_prop_icon_name_get(const EDBus_Service_Interface *iface EINA_UNUSED,
181 const char *propname EINA_UNUSED,
182 EDBus_Message_Iter *iter,
183 const EDBus_Message *request_msg EINA_UNUSED,
184 EDBus_Message **error EINA_UNUSED)
185{
186 const char *s = _item.icon_name ? _item.icon_name : "";
187
188 edbus_message_iter_basic_append(iter, 's', s);
189
190 return EINA_TRUE;
191}
192
193static Eina_Bool
194_prop_icon_theme_path_get(const EDBus_Service_Interface *iface EINA_UNUSED,
195 const char *propname EINA_UNUSED,
196 EDBus_Message_Iter *iter,
197 const EDBus_Message *request_msg EINA_UNUSED,
198 EDBus_Message **error EINA_UNUSED)
199{
200 const char *s = _item.icon_theme_path ? _item.icon_theme_path : "";
201
202 edbus_message_iter_basic_append(iter, 's', s);
203
204 return EINA_TRUE;
205}
206
207static Eina_Bool
208_prop_id_get(const EDBus_Service_Interface *iface EINA_UNUSED,
209 const char *propname EINA_UNUSED,
210 EDBus_Message_Iter *iter,
211 const EDBus_Message *request_msg EINA_UNUSED,
212 EDBus_Message **error EINA_UNUSED)
213{
214 const char *s = _item.id ? _item.id : "";
215
216 edbus_message_iter_basic_append(iter, 's', s);
217
218 return EINA_TRUE;
219}
220
221static Eina_Bool
222_prop_menu_get(const EDBus_Service_Interface *iface EINA_UNUSED,
223 const char *propname EINA_UNUSED,
224 EDBus_Message_Iter *iter,
225 const EDBus_Message *request_msg EINA_UNUSED,
226 EDBus_Message **error EINA_UNUSED)
227{
228 const char *s = _item.menu ? _item.menu : "/";
229
230 edbus_message_iter_basic_append(iter, 'o', s);
231
232 return EINA_TRUE;
233}
234
235static Eina_Bool
236_prop_status_get(const EDBus_Service_Interface *iface EINA_UNUSED,
237 const char *propname EINA_UNUSED,
238 EDBus_Message_Iter *iter,
239 const EDBus_Message *request_msg EINA_UNUSED,
240 EDBus_Message **error EINA_UNUSED)
241{
242 edbus_message_iter_basic_append(iter, 's',
243 _Elm_Systray_Status_Str[_item.status]);
244
245 return EINA_TRUE;
246}
247
248static Eina_Bool
249_prop_title_get(const EDBus_Service_Interface *iface EINA_UNUSED,
250 const char *propname EINA_UNUSED,
251 EDBus_Message_Iter *iter,
252 const EDBus_Message *request_msg EINA_UNUSED,
253 EDBus_Message **error EINA_UNUSED)
254{
255 const char *s = _item.title ? _item.title : "";
256
257 edbus_message_iter_basic_append(iter, 's', s);
258
259 return EINA_TRUE;
260}
261
262static Eina_Bool
263_prop_xayatana_orderindex_get(const EDBus_Service_Interface *iface EINA_UNUSED,
264 const char *propname EINA_UNUSED,
265 EDBus_Message_Iter *iter,
266 const EDBus_Message *request_msg EINA_UNUSED,
267 EDBus_Message **error EINA_UNUSED)
268{
269 edbus_message_iter_basic_append(iter, 'u', 0);
270
271 return EINA_TRUE;
272}
273
274static const EDBus_Property properties[] = {
275 { "AttentionAcessibleDesc", "s", _prop_str_empty_get, NULL, 0 },
276 { "AttentionIconName", "s", _prop_attention_icon_name_get, NULL, 0 },
277 { "Category", "s", _prop_category_get, NULL, 0 },
278 { "IconAcessibleDesc", "s", _prop_str_empty_get, NULL, 0 },
279 { "IconName", "s", _prop_icon_name_get, NULL, 0 },
280 { "IconThemePath", "s", _prop_icon_theme_path_get, NULL, 0 },
281 { "Id", "s", _prop_id_get, NULL, 0 },
282 { "Menu", "o", _prop_menu_get, NULL, 0 },
283 { "Status", "s", _prop_status_get, NULL, 0 },
284 { "Title", "s", _prop_title_get, NULL, 0 },
285 { "XAyatanaLabelGuide", "s", _prop_str_empty_get, NULL, 0 },
286 { "XAyatanaLabel", "s", _prop_str_empty_get, NULL, 0 },
287 { "XAyatanaOrderingIndex", "u", _prop_xayatana_orderindex_get, NULL, 0 },
288 { NULL, NULL, NULL, NULL, 0 }
289};
290
291static const EDBus_Service_Interface_Desc _iface_desc = {
292 INTERFACE, methods, signals, properties, NULL, NULL
293};
294#endif
295// =============================================================================
296
297static void
298_menu_died(void *data EINA_UNUSED,
299 Evas *e EINA_UNUSED,
300 Evas_Object *obj EINA_UNUSED,
301 void *event_info EINA_UNUSED)
302{
303 _item.menu_obj = NULL;
304
305 eina_stringshare_replace(&(_item.menu), NULL);
306
307#ifdef ELM_EDBUS2
308 edbus_service_property_changed(_iface, "Menu");
309#endif
310}
311
312static void
313_category_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
314{
315 Elm_Systray_Category cat = va_arg(*args, Elm_Systray_Category);
316
317 if (_item.cat == cat) return;
318
319 _item.cat = cat;
320#ifdef ELM_EDBUS2
321 edbus_service_property_changed(_iface, "Category");
322#endif
323}
324
325static void
326_category_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
327{
328 Elm_Systray_Category *ret = va_arg(*args, Elm_Systray_Category *);
329
330 *ret = _item.cat;
331}
332
333static void
334_status_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
335{
336 Elm_Systray_Status st = va_arg(*args, Elm_Systray_Status);
337
338 if (_item.status == st) return;
339
340 _item.status = st;
341#ifdef ELM_EDBUS2
342 edbus_service_property_changed(_iface, "Status");
343 _elm_systray_signal_emit(ELM_SYSTRAY_SIGNAL_NEWSTATUS,
344 _Elm_Systray_Status_Str[_item.status]);
345#endif
346}
347
348static void
349_status_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
350{
351 Elm_Systray_Status *ret = va_arg(*args, Elm_Systray_Status *);
352 *ret = _item.status;
353}
354
355static void
356_att_icon_name_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
357{
358 const char *att_icon_name = va_arg(*args, const char *);
359
360 if (!eina_stringshare_replace(&(_item.att_icon_name), att_icon_name)) return;
361
362#ifdef ELM_EDBUS2
363 edbus_service_property_changed(_iface, "AttentionIconName");
364 _elm_systray_signal_emit(ELM_SYSTRAY_SIGNAL_NEWATTENTIONICON, NULL);
365#endif
366}
367
368static void
369_att_icon_name_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
370{
371 const char **ret = va_arg(*args, const char **);
372 *ret = _item.att_icon_name;
373}
374
375static void
376_icon_name_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
377{
378 const char *icon_name = va_arg(*args, const char *);
379
380 if (!eina_stringshare_replace(&(_item.icon_name), icon_name)) return;
381
382#ifdef ELM_EDBUS2
383 edbus_service_property_changed(_iface, "IconName");
384 _elm_systray_signal_emit(ELM_SYSTRAY_SIGNAL_NEWICON, NULL);
385#endif
386}
387
388static void
389_icon_name_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
390{
391 const char **ret = va_arg(*args, const char **);
392 *ret = _item.icon_name;
393}
394
395static void
396_icon_theme_path_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
397{
398 const char *icon_theme_path = va_arg(*args, const char *);
399
400 if (!eina_stringshare_replace(&(_item.icon_theme_path), icon_theme_path))
401 return;
402
403#ifdef ELM_EDBUS2
404 edbus_service_property_changed(_iface, "IconThemePath");
405 _elm_systray_signal_emit(ELM_SYSTRAY_SIGNAL_NEWICONTHEMEPATH,
406 _item.icon_theme_path);
407#endif
408}
409
410static void
411_icon_theme_path_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
412{
413 const char **ret = va_arg(*args, const char **);
414 *ret = _item.icon_theme_path;
415}
416
417static void
418_id_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
419{
420 const char *id = va_arg(*args, const char *);
421
422 if (!eina_stringshare_replace(&(_item.id), id)) return;
423
424#ifdef ELM_EDBUS2
425 edbus_service_property_changed(_iface, "Id");
426#endif
427}
428
429static void
430_id_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
431{
432 const char **ret = va_arg(*args, const char **);
433 *ret = _item.id;
434}
435
436static void
437_title_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
438{
439 const char *title = va_arg(*args, const char *);
440
441 if (!eina_stringshare_replace(&(_item.title), title)) return;
442
443#ifdef ELM_EDBUS2
444 edbus_service_property_changed(_iface, "Title");
445 _elm_systray_signal_emit(ELM_SYSTRAY_SIGNAL_NEWTITLE, NULL);
446#endif
447}
448
449static void
450_title_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
451{
452 const char **ret = va_arg(*args, const char **);
453 *ret = _item.title;
454}
455
456static void
457_menu_set(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
458{
459 const Eo *menu_obj = va_arg(*args, const Eo *);
460 const char *menu = NULL;
461
462 if (_item.menu_obj == menu_obj) return;
463
464 if (menu_obj)
465 {
466 menu = _elm_dbus_menu_register((Eo *) menu_obj);
467 evas_object_event_callback_add((Evas_Object *) menu_obj,
468 EVAS_CALLBACK_DEL, _menu_died, NULL);
469 }
470
471 eina_stringshare_replace(&(_item.menu), menu);
472
473 if (_item.menu_obj)
474 evas_object_event_callback_del_full((Evas_Object *) _item.menu_obj,
475 EVAS_CALLBACK_DEL, _menu_died, NULL);
476
477 _item.menu_obj = menu_obj;
478
479#ifdef ELM_EDBUS2
480 edbus_service_property_changed(_iface, "Menu");
481#endif
482}
483
484static void
485_menu_get(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
486{
487 const Eo **ret = va_arg(*args, const Eo **);
488 *ret = _item.menu_obj;
489}
490
491static void
492_register(Eo *obj EINA_UNUSED, void *priv EINA_UNUSED, va_list *args)
493{
494 Eina_Bool *ret = va_arg(*args, Eina_Bool *);
495#ifdef ELM_EDBUS2
496 if (!_elm_need_systray) goto err;
497
498 *ret = _elm_systray_watcher_status_notifier_item_register(OBJ_PATH);
499 return;
500
501err:
502#endif
503 *ret = EINA_FALSE;
504}
505
506EAPI Eina_Bool
507elm_need_systray(void)
508{
509#ifdef ELM_EDBUS2
510 if (_elm_need_systray) return EINA_TRUE;
511
512 if (!elm_need_edbus()) return EINA_FALSE;
513
514 if (!ELM_EVENT_SYSTRAY_READY)
515 ELM_EVENT_SYSTRAY_READY = ecore_event_type_new();
516
517 if (!_elm_systray_watcher_init()) return EINA_FALSE;
518
519 _conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
520 if (!_conn) goto err;
521
522 _iface = edbus_service_interface_register(_conn, OBJ_PATH, &_iface_desc);
523 if (!_iface) goto err;
524
525 _elm_need_systray = EINA_TRUE;
526 return EINA_TRUE;
527
528err:
529 if (_conn)
530 {
531 edbus_connection_unref(_conn);
532 _conn = NULL;
533 }
534
535 _elm_systray_watcher_shutdown();
536#endif
537 return EINA_FALSE;
538}
539
540void
541_elm_unneed_systray(void)
542{
543#ifdef ELM_EDBUS2
544 if (!_elm_need_systray) return;
545
546 _elm_need_systray = EINA_FALSE;
547
548 edbus_service_interface_unregister(_iface);
549
550 edbus_connection_unref(_conn);
551
552 _elm_systray_watcher_shutdown();
553
554 eina_stringshare_del(_item.att_icon_name);
555 eina_stringshare_del(_item.icon_name);
556 eina_stringshare_del(_item.icon_theme_path);
557 eina_stringshare_del(_item.id);
558 eina_stringshare_del(_item.title);
559 eina_stringshare_del(_item.menu);
560
561 if (_item.menu_obj)
562 {
563 evas_object_event_callback_del_full((Evas_Object *) _item.menu_obj,
564 EVAS_CALLBACK_DEL, _menu_died,
565 NULL);
566 _item.menu_obj = NULL;
567 }
568#endif
569}
570
571// =============================================================================
572// EObject Stuff
573// =============================================================================
574static void
575_class_constructor(Eo_Class *klass)
576{
577 const Eo_Op_Func_Description func_desc[] = {
578 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_SET),
579 _category_set),
580 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_GET),
581 _category_get),
582 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_SET),
583 _status_set),
584 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_GET),
585 _status_get),
586 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_SET),
587 _att_icon_name_set),
588 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_GET),
589 _att_icon_name_get),
590 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_SET),
591 _icon_name_set),
592 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_GET),
593 _icon_name_get),
594 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_SET),
595 _icon_theme_path_set),
596 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_GET),
597 _icon_theme_path_get),
598 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ID_SET),
599 _id_set),
600 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ID_GET),
601 _id_get),
602 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_SET),
603 _title_set),
604 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_GET),
605 _title_get),
606 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_MENU_SET),
607 _menu_set),
608 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_MENU_GET),
609 _menu_get),
610 EO_OP_FUNC(ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_REGISTER),
611 _register),
612 EO_OP_FUNC_SENTINEL
613 };
614 eo_class_funcs_set(klass, func_desc);
615}
616
617static const Eo_Op_Description op_desc[] = {
618 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_SET, ""),
619 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_GET, ""),
620 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_SET, ""),
621 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_GET, ""),
622 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_SET, ""),
623 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_GET, ""),
624 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_SET, ""),
625 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_GET, ""),
626 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_SET, ""),
627 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_GET, ""),
628 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ID_SET, ""),
629 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_ID_GET, ""),
630 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_SET, ""),
631 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_GET, ""),
632 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_MENU_SET, ""),
633 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_MENU_GET, ""),
634 EO_OP_DESCRIPTION(ELM_OBJ_SYSTRAY_SUB_ID_REGISTER, ""),
635 EO_OP_DESCRIPTION_SENTINEL
636};
637
638static const Eo_Class_Description class_desc = {
639 EO_VERSION,
640 "elm_systray",
641 EO_CLASS_TYPE_REGULAR,
642 EO_CLASS_DESCRIPTION_OPS
643 (&ELM_OBJ_SYSTRAY_BASE_ID, op_desc, ELM_OBJ_SYSTRAY_SUB_ID_LAST),
644 NULL,
645 0,
646 _class_constructor,
647 NULL//_class_destructor,
648};
649
650EO_DEFINE_CLASS(elm_obj_systray_class_get, &class_desc, EO_BASE_CLASS, NULL);
diff --git a/src/lib/elm_systray.h b/src/lib/elm_systray.h
new file mode 100644
index 000000000..225daa773
--- /dev/null
+++ b/src/lib/elm_systray.h
@@ -0,0 +1,324 @@
1#ifndef ELM_SYSTRAY_H
2#define ELM_SYSTRAY_H
3
4#include "Eo.h"
5
6#define ELM_OBJ_SYSTRAY_CLASS elm_obj_systray_class_get()
7
8const Eo_Class *elm_obj_systray_class_get(void) EINA_CONST;
9
10extern EAPI Eo_Op ELM_OBJ_SYSTRAY_BASE_ID;
11
12enum
13{
14 ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_SET,
15 ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_GET,
16 ELM_OBJ_SYSTRAY_SUB_ID_STATUS_SET,
17 ELM_OBJ_SYSTRAY_SUB_ID_STATUS_GET,
18 ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_SET,
19 ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_GET,
20 ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_SET,
21 ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_GET,
22 ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_SET,
23 ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_GET,
24 ELM_OBJ_SYSTRAY_SUB_ID_ID_SET,
25 ELM_OBJ_SYSTRAY_SUB_ID_ID_GET,
26 ELM_OBJ_SYSTRAY_SUB_ID_TITLE_SET,
27 ELM_OBJ_SYSTRAY_SUB_ID_TITLE_GET,
28 ELM_OBJ_SYSTRAY_SUB_ID_MENU_SET,
29 ELM_OBJ_SYSTRAY_SUB_ID_MENU_GET,
30 ELM_OBJ_SYSTRAY_SUB_ID_REGISTER,
31 ELM_OBJ_SYSTRAY_SUB_ID_LAST
32};
33
34#define ELM_OBJ_SYSTRAY_ID(sub_id) (ELM_OBJ_SYSTRAY_BASE_ID + sub_id)
35
36/**
37 * @def elm_obj_systray_category_set
38 *
39 * Set the category of the Status Notifier Item.
40 *
41 * @param[in] cat Category
42 *
43 * @see Elm_Systray_Category
44 *
45 * @since 1.8
46 */
47#define elm_obj_systray_category_set(cat) \
48 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_SET), \
49 EO_TYPECHECK(Elm_Systray_Category, cat)
50
51/**
52 * @def elm_obj_systray_category_get
53 *
54 * Retrieve the category of the Status Notifier Item.
55 *
56 * @param[out] ret Category
57 *
58 * @see elm_obj_systray_category_set
59 *
60 * @since 1.8
61 */
62#define elm_obj_systray_category_get(ret) \
63 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_CATEGORY_GET), \
64 EO_TYPECHECK(Elm_Systray_Category *, ret)
65
66/**
67 * @def elm_obj_systray_status_set
68 *
69 * Set the status of the Status Notifier Item.
70 *
71 * @param[in] st Status
72 *
73 * @see Elm_Systray_Status
74 *
75 * @since 1.8
76 */
77#define elm_obj_systray_status_set(st) \
78 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_SET), \
79 EO_TYPECHECK(Elm_Systray_Status, st)
80
81/**
82 * @def elm_obj_systray_status_get
83 *
84 * Retrieve the status of the Status Notifier Item.
85 *
86 * @param[out] ret Status
87 *
88 * @see elm_obj_systray_status_set
89 *
90 * @since 1.8
91 */
92#define elm_obj_systray_status_get(ret) \
93 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_STATUS_GET), \
94 EO_TYPECHECK(Elm_Systray_Status *, ret)
95
96/**
97 * @def elm_obj_systray_att_icon_name_set
98 *
99 * Set the name of the attention icon to be used by the Status Notifier Item.
100 *
101 * @param[in] att_icon_name
102 *
103 * @see elm_obj_systray_att_icon_name_get
104 *
105 * @since 1.8
106 */
107#define elm_obj_systray_att_icon_name_set(att_icon_name) \
108 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_SET), \
109 EO_TYPECHECK(const char *, att_icon_name)
110
111/**
112 * @def elm_obj_systray_att_icon_name_get
113 *
114 * Retrieve the name of the attention icon used by the Status Notifier Item.
115 *
116 * @param[out] ret
117 *
118 * @see elm_obj_systray_att_icon_name_set
119 *
120 * @since 1.8
121 */
122#define elm_obj_systray_att_icon_name_get(ret) \
123 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ATT_ICON_NAME_GET), \
124 EO_TYPECHECK(const char **, ret)
125
126/**
127 * @def elm_obj_systray_icon_name_set
128 *
129 * Set the name of the icon to be used by the Status Notifier Item.
130 *
131 * @param[in] icon_name
132 *
133 * @see elm_obj_systray_icon_name_get
134 *
135 * @since 1.8
136 */
137#define elm_obj_systray_icon_name_set(icon_name) \
138 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_SET), \
139 EO_TYPECHECK(const char *, icon_name)
140
141/**
142 * @def elm_obj_systray_icon_name_get
143 *
144 * Retrieve the name of the icon used by the Status Notifier Item.
145 *
146 * @param[out] ret
147 *
148 * @see elm_obj_systray_icon_name_set
149 *
150 * @since 1.8
151 */
152#define elm_obj_systray_icon_name_get(ret) \
153 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_NAME_GET), \
154 EO_TYPECHECK(const char **, ret)
155
156/**
157 * @def elm_obj_systray_icon_theme_path_set
158 *
159 * Set the path to the theme where the icons can be found.
160 * Set this value to "" to use the default path.
161 *
162 * @param[in] icon_theme_path
163 *
164 * @see elm_obj_systray_icon_theme_path_get
165 *
166 * @since 1.8
167 */
168#define elm_obj_systray_icon_theme_path_set(icon_theme_path) \
169 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_SET), \
170 EO_TYPECHECK(const char *, icon_theme_path)
171
172/**
173 * @def elm_obj_systray_icon_theme_path_get
174 *
175 * Retrieve the path to the icon's theme currently in use.
176 *
177 * @param[out] ret
178 *
179 * @see elm_obj_systray_icon_theme_path_set
180 *
181 * @since 1.8
182 */
183#define elm_obj_systray_icon_theme_path_get(ret) \
184 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ICON_THEME_PATH_GET), \
185 EO_TYPECHECK(const char **, ret)
186
187/**
188 * @def elm_obj_systray_id_set
189 *
190 * Set the id of the Status Notifier Item.
191 *
192 * @param[in] id
193 *
194 * @see elm_obj_systray_id_get
195 *
196 * @since 1.8
197 */
198#define elm_obj_systray_id_set(id) \
199 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ID_SET), \
200 EO_TYPECHECK(const char *, id)
201
202/**
203 * @def elm_obj_systray_id_get
204 *
205 * Retrieve the id of the Status Notifier Item.
206 *
207 * @param[out] ret
208 *
209 * @see elm_obj_systray_id_set
210 *
211 * @since 1.8
212 */
213#define elm_obj_systray_id_get(ret) \
214 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_ID_GET), \
215 EO_TYPECHECK(const char **, ret)
216
217/**
218 * @def elm_obj_systray_title_set
219 *
220 * Set the title of the Status Notifier Item.
221 *
222 * @param[in] title
223 *
224 * @see elm_obj_systray_title_get
225 *
226 * @since 1.8
227 */
228#define elm_obj_systray_title_set(title) \
229 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_SET), \
230 EO_TYPECHECK(const char *, title)
231
232/**
233 * @def elm_obj_systray_title_get
234 *
235 * Retrieve the title of the Status Notifier Item.
236 *
237 * @param[out] ret
238 *
239 * @see elm_obj_systray_title_set
240 *
241 * @since 1.8
242 */
243#define elm_obj_systray_title_get(ret) \
244 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_TITLE_GET), \
245 EO_TYPECHECK(const char **, ret)
246
247/**
248 * @def elm_obj_systray_menu_set
249 *
250 * Set the object path of the D-Bus Menu that is to be show when the
251 * Status Notifier Item is activated by the user.
252 *
253 * @param[in] menu
254 *
255 * @see elm_obj_systray_menu_get
256 *
257 * @since 1.8
258 */
259#define elm_obj_systray_menu_set(menu) \
260 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_MENU_SET), \
261 EO_TYPECHECK(const Eo *, menu)
262
263/**
264 * @def elm_obj_systray_menu_get
265 *
266 * Retrieve the object path of the D-Bus Menu currently in use.
267 *
268 * @param[out] ret
269 *
270 * @see elm_obj_systray_menu_set
271 *
272 * @since 1.8
273 */
274#define elm_obj_systray_menu_get(ret) \
275 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_MENU_GET), \
276 EO_TYPECHECK(const Eo **, ret)
277
278/**
279 * @def elm_obj_systray_register
280 *
281 * Register this Status Notifier Item in the System Tray Watcher.
282 * This function should only be called after the event
283 * ELM_EVENT_SYSTRAY_READY is emitted.
284 *
285 * @param[out] ret
286 *
287 * @since 1.8
288 */
289#define elm_obj_systray_register(ret) \
290 ELM_OBJ_SYSTRAY_ID(ELM_OBJ_SYSTRAY_SUB_ID_REGISTER), \
291 EO_TYPECHECK(Eina_Bool *, ret)
292
293/**
294 * Emitted when the systray is ready to be used by the application.
295 */
296EAPI extern int ELM_EVENT_SYSTRAY_READY;
297
298/**
299 * Category of the Status Notifier Item.
300 *
301 * @since 1.8
302 */
303typedef enum _Elm_Systray_Category
304{
305 ELM_SYSTRAY_CATEGORY_APP_STATUS, /**< Indicators of application status */
306 ELM_SYSTRAY_CATEGORY_COMMUNICATIONS, /**< Communications apps */
307 ELM_SYSTRAY_CATEGORY_SYS_SERVICES, /**< System Service apps */
308 ELM_SYSTRAY_CATEGORY_HARDWARE, /**< Hardware indicators */
309 ELM_SYSTRAY_CATEGORY_OTHER /**< Undefined category */
310} Elm_Systray_Category;
311
312/**
313 * Application status information.
314 *
315 * @since 1.8
316 */
317typedef enum _Elm_Systray_Status
318{
319 ELM_SYSTRAY_STATUS_PASSIVE, /**< Passive (normal) */
320 ELM_SYSTRAY_STATUS_ACTIVE, /**< Active */
321 ELM_SYSTRAY_STATUS_ATTENTION /**< Needs Attention */
322} Elm_Systray_Status;
323
324#endif
diff --git a/src/lib/elm_systray_watcher.c b/src/lib/elm_systray_watcher.c
new file mode 100644
index 000000000..196381ec9
--- /dev/null
+++ b/src/lib/elm_systray_watcher.c
@@ -0,0 +1,126 @@
1#include "Elementary.h"
2#include "elm_priv.h"
3
4#include "elm_systray_watcher.h"
5
6#ifdef ELM_EDBUS2
7#define OBJ "/StatusNotifierWatcher"
8#define BUS "org.kde.StatusNotifierWatcher"
9#define INTERFACE "org.kde.StatusNotifierWatcher"
10
11static Eina_Bool _elm_systray_watcher = EINA_FALSE;
12
13static EDBus_Connection *_watcher_conn = NULL;
14static EDBus_Object *_watcher_obj = NULL;
15static EDBus_Proxy *_watcher_proxy = NULL;
16
17static void
18_status_notifier_item_register_cb(void *data EINA_UNUSED,
19 const EDBus_Message *msg,
20 EDBus_Pending *pending EINA_UNUSED)
21{
22 const char *errname, *errmsg;
23
24 if (edbus_message_error_get(msg, &errname, &errmsg))
25 ERR("Edbus Error: %s %s", errname, errmsg);
26}
27#endif
28
29Eina_Bool
30_elm_systray_watcher_status_notifier_item_register(const char *obj)
31{
32#ifdef ELM_EDBUS2
33 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
34 EINA_SAFETY_ON_NULL_RETURN_VAL(_watcher_proxy, EINA_FALSE);
35
36 if (!edbus_proxy_call(_watcher_proxy, "RegisterStatusNotifierItem",
37 _status_notifier_item_register_cb,
38 NULL, -1, "s", obj))
39 {
40 ERR("Error sending message: "INTERFACE".RegisterStatusNotifierItem.");
41 return EINA_FALSE;
42 }
43
44 return EINA_TRUE;
45#else
46 (void) obj;
47 return EINA_FALSE;
48#endif
49}
50
51#ifdef ELM_EDBUS2
52static void
53_release(void)
54{
55 if (_watcher_proxy)
56 {
57 edbus_proxy_unref(_watcher_proxy);
58 _watcher_proxy = NULL;
59 }
60
61 if (_watcher_obj)
62 {
63 edbus_object_unref(_watcher_obj);
64 _watcher_obj = NULL;
65 }
66}
67
68static void
69_update(void)
70{
71 _release();
72
73 _watcher_obj = edbus_object_get(_watcher_conn, BUS, OBJ);
74 _watcher_proxy = edbus_proxy_get(_watcher_obj, INTERFACE);
75
76 ecore_event_add(ELM_EVENT_SYSTRAY_READY, NULL, NULL, NULL);
77}
78
79static void
80_name_owner_changed_cb(void *data EINA_UNUSED,
81 const char *bus EINA_UNUSED,
82 const char *old_id EINA_UNUSED,
83 const char *new_id)
84{
85 if ((!new_id) || (*new_id == '\0'))
86 _release();
87 else
88 _update();
89}
90#endif
91
92Eina_Bool
93_elm_systray_watcher_init(void)
94{
95#ifdef ELM_EDBUS2
96 if (_elm_systray_watcher) return EINA_TRUE;
97
98 if (!elm_need_edbus()) return EINA_FALSE;
99
100 _watcher_conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
101
102 edbus_name_owner_changed_callback_add(_watcher_conn, BUS,
103 _name_owner_changed_cb, NULL,
104 EINA_TRUE);
105
106 _elm_systray_watcher = EINA_TRUE;
107 return EINA_TRUE;
108#else
109 return EINA_FALSE;
110#endif
111}
112
113void
114_elm_systray_watcher_shutdown(void)
115{
116#ifdef ELM_EDBUS2
117 if (!_elm_systray_watcher) return;
118
119 _elm_systray_watcher = EINA_FALSE;
120
121 _release();
122
123 edbus_connection_unref(_watcher_conn);
124 _watcher_conn = NULL;
125#endif
126}
diff --git a/src/lib/elm_systray_watcher.h b/src/lib/elm_systray_watcher.h
new file mode 100644
index 000000000..337cce6d7
--- /dev/null
+++ b/src/lib/elm_systray_watcher.h
@@ -0,0 +1,10 @@
1#ifndef ELM_SYSTRAY_WATCHER_H
2#define ELM_SYSTRAY_WATCHER_H
3
4Eina_Bool _elm_systray_watcher_status_notifier_item_register(const char *obj);
5
6Eina_Bool _elm_systray_watcher_init(void);
7
8void _elm_systray_watcher_shutdown(void);
9
10#endif