elm: add system notification.

SVN revision: 80281
This commit is contained in:
Gustavo Sverzut Barbieri 2012-12-05 22:24:00 +00:00
parent 10cb9bcf73
commit 27c6def19d
11 changed files with 474 additions and 0 deletions

View File

@ -752,6 +752,7 @@
* Add elm_app_name_set/get(): Formal application name string.
* Add elm_app_destkop_entry_set/get(): Path to '.desktop' file.
* Add elm_sys_notify to expose System Notifications (D-Bus atm).
2012-12-04 Gwanglim Lee

View File

@ -121,6 +121,7 @@ test_slider.c \
test_slideshow.c \
test_spinner.c \
test_store.c \
test_sys_notify.c \
test_table.c \
test_thumb.c \
test_toolbar.c \

View File

@ -177,6 +177,7 @@ void test_ctxpopup(void *data, Evas_Object *obj, void *event_info);
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_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);
@ -723,6 +724,9 @@ add_tests:
ADD_TEST(NULL, "Helpers", "Store", test_store);
// ADD_TEST(NULL, "Helpers", "Factory", test_factory);
//------------------------------//
ADD_TEST(NULL, "System", "Notification", test_sys_notify);
//------------------------------//
ADD_TEST(NULL, "Micellaneous", "Copy And Paste", test_cnp);
ADD_TEST(NULL, "Micellaneous", "Weather", test_weather);

View File

@ -0,0 +1,69 @@
#ifdef HAVE_CONFIG_H
# include "elementary_config.h"
#endif
#include <Elementary.h>
#ifndef ELM_LIB_QUICKLAUNCH
#define WIDTH 320
#define HEIGHT 160
static Evas_Object *s = NULL;
static Evas_Object *b = NULL;
static void
_bt_clicked(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
{
elm_sys_notify_simple_send("", elm_entry_entry_get(s), elm_entry_entry_get(b));
}
void
test_sys_notify(void *data __UNUSED__,
Evas_Object *obj __UNUSED__,
void *event_info __UNUSED__)
{
Evas_Object *win, *bx, *it;
elm_need_sys_notify();
win = elm_win_add(NULL, "Sys Notify", ELM_WIN_BASIC);
elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
elm_win_title_set(win, "System Notification");
elm_win_autodel_set(win, EINA_TRUE);
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);
s = elm_entry_add(win);
elm_entry_single_line_set(s, EINA_TRUE);
elm_entry_scrollable_set(s, EINA_TRUE);
elm_entry_entry_set(s, "Summary");
evas_object_size_hint_align_set(s, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_box_pack_end(bx, s);
evas_object_show(s);
b = elm_entry_add(win);
elm_entry_single_line_set(b, EINA_TRUE);
elm_entry_scrollable_set(b, EINA_TRUE);
elm_entry_entry_set(b, "Body long description.");
evas_object_size_hint_align_set(b, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_box_pack_end(bx, b);
evas_object_show(b);
it = elm_button_add(win);
elm_object_text_set(it, "Send Notification");
evas_object_smart_callback_add(it, "clicked", _bt_clicked, NULL);
elm_box_pack_end(bx, it);
evas_object_show(it);
evas_object_resize(win, WIDTH, HEIGHT);
evas_object_show(win);
}
#endif

View File

@ -158,6 +158,7 @@ EAPI extern Elm_Version *elm_version;
#include <elm_prefs_data.h>
#include <elm_prefs.h>
#include <elm_sys_notify.h>
/* special widgets - types used elsewhere */
#include <elm_icon.h>

View File

@ -193,6 +193,7 @@ elm_slider.h \
elm_slideshow.h \
elm_spinner.h \
elm_store.h \
elm_sys_notify.h \
elm_table.h \
elm_theme.h \
elm_thumb.h \
@ -279,6 +280,7 @@ elm_slider.c \
elm_slideshow.c \
elm_spinner.c \
elm_store.c \
elm_sys_notify.c \
elm_table.c \
elm_theme.c \
elm_thumb.c \

View File

@ -623,6 +623,7 @@ elm_quicklaunch_shutdown(void)
_elm_exit_handler = NULL;
_elm_theme_shutdown();
_elm_unneed_sys_notify();
_elm_unneed_efreet();
_elm_unneed_e_dbus();
_elm_unneed_edbus();

View File

@ -11,6 +11,20 @@
*/
EAPI Eina_Bool elm_need_efreet(void);
/**
* Request that your elementary application needs Elm_Sys_Notify
*
* This initializes the Elm_Sys_Notify when called and if support exists
* it returns EINA_TRUE, otherwise returns EINA_FALSE. This must be called
* before any elm_sys_notify calls.
*
* @return EINA_TRUE if support exists and initialization succeeded.
*
* @ingroup Elm_Sys_Notify
* @since 1.8
*/
EAPI Eina_Bool elm_need_sys_notify(void);
/**
* Request that your elementary application needs e_dbus
*

View File

@ -327,6 +327,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_sys_notify(void);
void _elm_unneed_ethumb(void);
void _elm_unneed_web(void);

View File

@ -0,0 +1,303 @@
#include <Elementary.h>
#include "elm_priv.h"
#define OBJ "/org/freedesktop/Notifications"
#define BUS "org.freedesktop.Notifications"
#define INTERFACE "org.freedesktop.Notifications"
#ifdef ELM_EDBUS2
static Eina_Bool _elm_need_sys_notify = EINA_FALSE;
static EDBus_Connection *_elm_sysnotif_conn = NULL;
static EDBus_Object *_elm_sysnotif_obj = NULL;
static EDBus_Proxy *_elm_sysnotif_proxy = NULL;
static Eina_Bool _has_markup = EINA_FALSE;
typedef struct _Elm_Sys_Notify_Send_Data
{
Elm_Sys_Notify_Send_Cb cb;
const void *data;
} Elm_Sys_Notify_Send_Data;
static void
_elm_sys_notify_marshal_dict_byte(EDBus_Message_Iter *array,
const char *key,
const char value)
{
EDBus_Message_Iter *var, *entry;
edbus_message_iter_arguments_set(array, "{sv}", &entry);
edbus_message_iter_basic_append(entry, 's', key);
var = edbus_message_iter_container_new(entry, 'v', "y");
edbus_message_iter_basic_append(var, 'y', value);
edbus_message_iter_container_close(entry, var);
edbus_message_iter_container_close(array, entry);
}
static void
_elm_sys_notify_marshal_dict_string(EDBus_Message_Iter *array,
const char *key,
const char *value)
{
EDBus_Message_Iter *var, *entry;
edbus_message_iter_arguments_set(array, "{sv}", &entry);
edbus_message_iter_basic_append(entry, 's', key);
var = edbus_message_iter_container_new(entry, 'v', "s");
edbus_message_iter_basic_append(var, 's', value);
edbus_message_iter_container_close(entry, var);
edbus_message_iter_container_close(array, entry);
}
static void
_get_capabilities_cb(void *data EINA_UNUSED,
const EDBus_Message *msg,
EDBus_Pending *pending EINA_UNUSED)
{
char *val;
EDBus_Message_Iter *arr;
if (edbus_message_error_get(msg, NULL, NULL) ||
!edbus_message_arguments_get(msg, "as", &arr)) goto end;
while(edbus_message_iter_get_and_next(arr, 's', &val))
if (!strcmp(val, "body-markup"))
{
_has_markup = EINA_TRUE;
return;
}
end:
_has_markup = EINA_FALSE;
}
void
_elm_sys_notify_capabilities_get(void)
{
EINA_SAFETY_ON_NULL_RETURN(_elm_sysnotif_proxy);
if (!edbus_proxy_call(_elm_sysnotif_proxy, "GetCapabilities",
_get_capabilities_cb, NULL, -1, ""))
ERR("Error sending message: "INTERFACE".GetCapabilities.");
}
static void
_close_notification_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))
{
if (errmsg && errmsg[0] == '\0')
INF("Notification no longer exists.");
else
ERR("Edbus Error: %s %s", errname, errmsg);
}
}
#endif
EAPI void
elm_sys_notify_close(unsigned int id)
{
#ifdef ELM_EDBUS2
EINA_SAFETY_ON_FALSE_RETURN(_elm_need_sys_notify);
EINA_SAFETY_ON_NULL_RETURN(_elm_sysnotif_proxy);
if (!edbus_proxy_call(_elm_sysnotif_proxy, "CloseNotification",
_close_notification_cb, NULL, -1, "u", id))
ERR("Error sending message: "INTERFACE".CloseNotification.");
#else
(void) id;
#endif
}
#ifdef ELM_EDBUS2
static void
_notify_cb(void *data,
const EDBus_Message *msg,
EDBus_Pending *pending EINA_UNUSED)
{
const char *errname, *errmsg;
Elm_Sys_Notify_Send_Data *d = data;
unsigned int id = 0;
if (edbus_message_error_get(msg, &errname, &errmsg))
ERR("Error: %s %s", errname, errmsg);
else if (!edbus_message_arguments_get(msg, "u", &id))
{
ERR("Error getting return values of "INTERFACE".Notify.");
id = 0;
}
if (d->cb) d->cb((void *)d->data, id);
free(d);
}
#endif
EAPI void
elm_sys_notify_send(unsigned int replaces_id, const char *icon,
const char *summary, const char *body,
Elm_Sys_Notify_Urgency urgency, int timeout,
Elm_Sys_Notify_Send_Cb cb, const void *cb_data)
{
#ifdef ELM_EDBUS2
EDBus_Message *msg;
EDBus_Message_Iter *iter, *actions, *hints;
Elm_Sys_Notify_Send_Data *data;
char *body_free = NULL;
char *desk_free = NULL;
const char *deskentry = elm_app_desktop_entry_get();
const char *appname = elm_app_name_get();
EINA_SAFETY_ON_FALSE_RETURN(_elm_need_sys_notify);
EINA_SAFETY_ON_NULL_RETURN(_elm_sysnotif_proxy);
data = malloc(sizeof(Elm_Sys_Notify_Send_Data));
EINA_SAFETY_ON_NULL_GOTO(data, error);
data->cb = cb;
data->data = cb_data;
if (!icon) icon = "";
if (!summary) summary = "";
if (!body)
body = "";
else if (!_has_markup)
body = body_free = elm_entry_markup_to_utf8(body);
msg = edbus_proxy_method_call_new(_elm_sysnotif_proxy, "Notify");
iter = edbus_message_iter_get(msg);
edbus_message_iter_arguments_set(iter, "susssas", appname, replaces_id, icon,
summary, body, &actions);
/* actions */
edbus_message_iter_container_close(iter, actions);
/* hints */
edbus_message_iter_arguments_set(iter, "a{sv}", &hints);
_elm_sys_notify_marshal_dict_byte(hints, "urgency", (char) urgency);
if (strcmp(deskentry, ""))
{
deskentry = ecore_file_file_get(deskentry);
deskentry = desk_free = ecore_file_strip_ext(deskentry);
_elm_sys_notify_marshal_dict_string(hints, "desktop_entry", deskentry);
}
edbus_message_iter_container_close(iter, hints);
/* timeout */
edbus_message_iter_arguments_set(iter, "i", timeout);
edbus_proxy_send(_elm_sysnotif_proxy, msg, _notify_cb, data, -1);
edbus_message_unref(msg);
free(desk_free);
free(body_free);
return;
error:
#else
(void) replaces_id;
(void) icon;
(void) summary;
(void) body;
(void) urgency;
(void) timeout;
#endif
if (cb) cb((void *)cb_data, 0);
}
#ifdef ELM_EDBUS2
static void
_release(void)
{
if (_elm_sysnotif_proxy)
{
edbus_proxy_unref(_elm_sysnotif_proxy);
_elm_sysnotif_proxy = NULL;
}
if (_elm_sysnotif_obj)
{
edbus_object_unref(_elm_sysnotif_obj);
_elm_sysnotif_obj = NULL;
}
}
static void
_update(void)
{
_release();
_elm_sysnotif_obj = edbus_object_get(_elm_sysnotif_conn, BUS, OBJ);
_elm_sysnotif_proxy = edbus_proxy_get(_elm_sysnotif_obj, INTERFACE);
_elm_sys_notify_capabilities_get();
}
static void
_name_owner_get_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);
else
_update();
}
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
EAPI Eina_Bool
elm_need_sys_notify(void)
{
#ifdef ELM_EDBUS2
if (_elm_need_sys_notify) return EINA_TRUE;
if (!elm_need_edbus()) return EINA_FALSE;
_elm_sysnotif_conn = edbus_connection_get(EDBUS_CONNECTION_TYPE_SESSION);
edbus_name_owner_changed_callback_add(_elm_sysnotif_conn, BUS,
_name_owner_changed_cb, NULL,
EINA_FALSE);
edbus_name_owner_get(_elm_sysnotif_conn, BUS, _name_owner_get_cb, NULL);
_elm_need_sys_notify = EINA_TRUE;
return EINA_TRUE;
#else
return EINA_FALSE;
#endif
}
void
_elm_unneed_sys_notify(void)
{
#ifdef ELM_EDBUS2
if (!_elm_need_sys_notify) return;
_elm_need_sys_notify = EINA_FALSE;
_release();
edbus_connection_unref(_elm_sysnotif_conn);
_elm_sysnotif_conn = NULL;
#endif
}

View File

@ -0,0 +1,77 @@
#ifndef ELM_SYS_NOTIFY_H
#define ELM_SYS_NOTIFY_H
/**
* Urgency levels of a notification
*
* @see elm_sys_notify_send()
*
* @since 1.8
*/
typedef enum _Elm_Sys_Notify_Urgency
{
ELM_SYS_NOTIFY_URGENCY_LOW,
ELM_SYS_NOTIFY_URGENCY_NORMAL,
ELM_SYS_NOTIFY_URGENCY_CRITICAL
} Elm_Sys_Notify_Urgency;
typedef void (*Elm_Sys_Notify_Send_Cb)(void *data, unsigned int id);
/**
* @def elm_sys_notify_simple_send
*
* Create a new notification just with Icon, Body and Summary.
*
* @param[in] icon
* @param[in] summary
* @param[in] body
*
* @see elm_sys_notify_send()
*
* @since 1.8
*/
#define elm_sys_notify_simple_send(icon, summary, body) \
elm_sys_notify_send(0, icon, summary, body, \
ELM_SYS_NOTIFY_URGENCY_NORMAL, \
-1, NULL, NULL)
/**
* Causes a notification to be forcefully closed and removed from the user's
* view. It can be used, for example, in the event that what the notification
* pertains to is no longer relevant, or to cancel a notification * with no
* expiration time.
*
* @param id Notification id
*
* @note If the notification no longer exists,
* an empty D-BUS Error message is sent back.
*
* @since 1.8
*/
EAPI void elm_sys_notify_close(unsigned int id);
/**
* Sends a notification to the notification server.
*
* @param replaces_id Notification ID that this notification replaces.
* The value 0 means a new notification.
* @param icon The optional program icon of the calling application.
* @param summary The summary text briefly describing the notification.
* @param body The optional detailed body text. Can be empty.
* @param urgency The urgency level.
* @param timeout Timeout display in milliseconds.
* @param cb Callback used to retrieve the notification id
* return by the Notification Server.
* @param cb_data Optional context data
*
* @since 1.8
*/
EAPI void elm_sys_notify_send(unsigned int replaces_id,
const char *icon,
const char *summary,
const char *body,
Elm_Sys_Notify_Urgency urgency,
int timeout,
Elm_Sys_Notify_Send_Cb cb,
const void *cb_data);
#endif