notifications - extend to support actions, links and img tags
we didn't support enough of noktifications to make everyone happy - this is why ffox, chrome etc. did their own notification windows and didn't use e's notifications. we now advertise doing everything. we say w edo sound though don't.... will add that later, but this now means we really do a lot more and thus pushes these other notifications into e's notifications so we're much better now and this annoyance i have noticed is now gone. @feat
This commit is contained in:
parent
1933f745f2
commit
b23eedae98
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
typedef struct _Notification_Data
|
typedef struct _Notification_Data
|
||||||
{
|
{
|
||||||
Eldbus_Connection *conn;
|
Eldbus_Connection *conn;
|
||||||
Eldbus_Service_Interface *iface;
|
Eldbus_Service_Interface *iface;
|
||||||
E_Notification_Notify_Cb notify_cb;
|
E_Notification_Notify_Cb notify_cb;
|
||||||
E_Notification_Close_Cb close_cb;
|
E_Notification_Close_Cb close_cb;
|
||||||
void *data;
|
void *data;
|
||||||
|
@ -15,15 +15,28 @@ static Notification_Data *n_data = NULL;
|
||||||
static void
|
static void
|
||||||
_notification_free(E_Notification_Notify *notify)
|
_notification_free(E_Notification_Notify *notify)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN(notify);
|
EINA_SAFETY_ON_NULL_RETURN(notify);
|
||||||
eina_stringshare_del(notify->app_name);
|
if (notify->app_name) eina_stringshare_del(notify->app_name);
|
||||||
eina_stringshare_del(notify->body);
|
if (notify->body) eina_stringshare_del(notify->body);
|
||||||
eina_stringshare_del(notify->icon.icon);
|
if (notify->icon.icon) eina_stringshare_del(notify->icon.icon);
|
||||||
if (notify->icon.icon_path)
|
if (notify->icon.icon_path) eina_stringshare_del(notify->icon.icon_path);
|
||||||
eina_stringshare_del(notify->icon.icon_path);
|
if (notify->summary) eina_stringshare_del(notify->summary);
|
||||||
eina_stringshare_del(notify->summary);
|
if (notify->icon.raw.data) free(notify->icon.raw.data);
|
||||||
if (notify->icon.raw.data)
|
if (notify->category) eina_stringshare_del(notify->category);
|
||||||
free(notify->icon.raw.data);
|
if (notify->desktop_entry) eina_stringshare_del(notify->desktop_entry);
|
||||||
|
if (notify->sound_file) eina_stringshare_del(notify->sound_file);
|
||||||
|
if (notify->sound_name) eina_stringshare_del(notify->sound_name);
|
||||||
|
if (notify->actions)
|
||||||
|
{
|
||||||
|
for (i = 0; notify->actions[i].action; i++)
|
||||||
|
{
|
||||||
|
eina_stringshare_del(notify->actions[i].action);
|
||||||
|
eina_stringshare_del(notify->actions[i].label);
|
||||||
|
}
|
||||||
|
free(notify->actions);
|
||||||
|
}
|
||||||
free(notify);
|
free(notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,12 +44,15 @@ static void
|
||||||
hints_dict_iter(void *data, const void *key, Eldbus_Message_Iter *var)
|
hints_dict_iter(void *data, const void *key, Eldbus_Message_Iter *var)
|
||||||
{
|
{
|
||||||
E_Notification_Notify *n = data;
|
E_Notification_Notify *n = data;
|
||||||
if (!strcmp(key, "image-data") || !strcmp(key, "image_data"))
|
|
||||||
|
if ((!strcmp(key, "image-data")) || (!strcmp(key, "image_data")) ||
|
||||||
|
(!strcmp(key, "icon_data")))
|
||||||
{
|
{
|
||||||
Eldbus_Message_Iter *st, *data_iter;
|
Eldbus_Message_Iter *st, *data_iter;
|
||||||
int w, h, r, bits, channels;
|
int w, h, r, bits, channels;
|
||||||
Eina_Bool alpha;
|
Eina_Bool alpha;
|
||||||
unsigned char *raw_data;
|
unsigned char *raw_data;
|
||||||
|
|
||||||
if (!eldbus_message_iter_arguments_get(var, "(iiibiiay)", &st))
|
if (!eldbus_message_iter_arguments_get(var, "(iiibiiay)", &st))
|
||||||
return;
|
return;
|
||||||
if (!eldbus_message_iter_arguments_get(st, "iiibiiay", &w, &h, &r,
|
if (!eldbus_message_iter_arguments_get(st, "iiibiiay", &w, &h, &r,
|
||||||
|
@ -54,22 +70,136 @@ hints_dict_iter(void *data, const void *key, Eldbus_Message_Iter *var)
|
||||||
n->icon.raw.data = malloc(sizeof(char) * n->icon.raw.data_size);
|
n->icon.raw.data = malloc(sizeof(char) * n->icon.raw.data_size);
|
||||||
EINA_SAFETY_ON_NULL_RETURN(n->icon.raw.data);
|
EINA_SAFETY_ON_NULL_RETURN(n->icon.raw.data);
|
||||||
memcpy(n->icon.raw.data, raw_data, sizeof(char) * n->icon.raw.data_size);
|
memcpy(n->icon.raw.data, raw_data, sizeof(char) * n->icon.raw.data_size);
|
||||||
}
|
printf("NOT: image-data=%ix%i,a=%i\n", w, h, alpha);
|
||||||
else if (!strcmp(key, "urgency"))
|
|
||||||
{
|
|
||||||
unsigned char urgency;
|
|
||||||
eldbus_message_iter_arguments_get(var, "y", &urgency);
|
|
||||||
if (urgency < 3)
|
|
||||||
n->urgency = urgency;
|
|
||||||
}
|
}
|
||||||
else if (!strcmp(key, "image-path") || !strcmp(key, "image_path"))
|
else if (!strcmp(key, "image-path") || !strcmp(key, "image_path"))
|
||||||
{
|
{
|
||||||
eldbus_message_iter_arguments_get(var, "s", &n->icon.icon_path);
|
eldbus_message_iter_arguments_get(var, "s", &n->icon.icon_path);
|
||||||
n->icon.icon_path = eina_stringshare_add(n->icon.icon_path);
|
n->icon.icon_path = eina_stringshare_add(n->icon.icon_path);
|
||||||
|
printf("NOT: image-path=[%s]\n", n->icon.icon_path);
|
||||||
|
// path to image file
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "urgency"))
|
||||||
|
{
|
||||||
|
unsigned char urgency;
|
||||||
|
|
||||||
|
eldbus_message_iter_arguments_get(var, "y", &urgency);
|
||||||
|
if (urgency < 3) n->urgency = urgency;
|
||||||
|
printf("NOT: urgency=%i\n", n->urgency);
|
||||||
|
// 0=low, 1=normal, 2=critical
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "category"))
|
||||||
|
{ // XXX: store category
|
||||||
|
const char *val = NULL;
|
||||||
|
|
||||||
|
eldbus_message_iter_arguments_get(var, "s", &val);
|
||||||
|
printf("NOT: category=[%s]\n", val);
|
||||||
|
// "device" A generic device-related notification that doesn't fit into any other category.
|
||||||
|
// "device.added" A device, such as a USB device, was added to the system.
|
||||||
|
// "device.error" A device had some kind of error.
|
||||||
|
// "device.removed" A device, such as a USB device, was removed from the system.
|
||||||
|
// "email" A generic e-mail-related notification that doesn't fit into any other category.
|
||||||
|
// "email.arrived" A new e-mail notification.
|
||||||
|
// "email.bounced" A notification stating that an e-mail has bounced.
|
||||||
|
// "im" A generic instant message-related notification that doesn't fit into any other category.
|
||||||
|
// "im.error" An instant message error notification.
|
||||||
|
// "im.received" A received instant message notification.
|
||||||
|
// "network" A generic network notification that doesn't fit into any other category.
|
||||||
|
// "network.connected" A network connection notification, such as successful sign-on to a network service. This should not be confused with device.added for new network devices.
|
||||||
|
// "network.disconnected" A network disconnected notification. This should not be confused with device.removed for disconnected network devices.
|
||||||
|
// "network.error" A network-related or connection-related error.
|
||||||
|
// "presence" A generic presence change notification that doesn't fit into any other category, such as going away or idle.
|
||||||
|
// "presence.offline" An offline presence change notification.
|
||||||
|
// "presence.online" An online presence change notification.
|
||||||
|
// "transfer" A generic file transfer or download notification that doesn't fit into any other category.
|
||||||
|
// "transfer.complete" A file transfer or download complete notification.
|
||||||
|
// "transfer.error" A file transfer or download error.
|
||||||
|
if (val) n->category = eina_stringshare_add(val);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "desktop-entry"))
|
||||||
|
{
|
||||||
|
const char *val = NULL;
|
||||||
|
|
||||||
|
eldbus_message_iter_arguments_get(var, "s", &val);
|
||||||
|
printf("NOT: desktop-entry=[%s]\n", val);
|
||||||
|
// if rage.desktop -> "rage"
|
||||||
|
// if terminology.desktop -> "terminology"
|
||||||
|
if (val) n->desktop_entry = eina_stringshare_add(val);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "icon-actions"))
|
||||||
|
{
|
||||||
|
Eina_Bool val = 0;
|
||||||
|
|
||||||
|
eldbus_message_iter_arguments_get(var, "b", &val);
|
||||||
|
printf("NOT: icon-actions=%i\n", val);
|
||||||
|
// 1 == interpret action identifier == named icon in icon naming standards
|
||||||
|
n->icon_actions = val;
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "resident"))
|
||||||
|
{
|
||||||
|
Eina_Bool val = 0;
|
||||||
|
|
||||||
|
eldbus_message_iter_arguments_get(var, "b", &val);
|
||||||
|
printf("NOT: resident=%i\n", val);
|
||||||
|
// 1== remove notification when action invoked - no timeout
|
||||||
|
n->resident = val;
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "supress-sound"))
|
||||||
|
{
|
||||||
|
Eina_Bool val = 0;
|
||||||
|
|
||||||
|
eldbus_message_iter_arguments_get(var, "b", &val);
|
||||||
|
printf("NOT: supress-sound=%i\n", val);
|
||||||
|
// 1== remove notification when action invoked - no timeout
|
||||||
|
n->suppress_sound = val;
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "sound-file"))
|
||||||
|
{
|
||||||
|
const char *val = NULL;
|
||||||
|
|
||||||
|
eldbus_message_iter_arguments_get(var, "s", &val);
|
||||||
|
printf("NOT: sound-file=[%s]\n", val);
|
||||||
|
// path to sound file to play
|
||||||
|
if (val) n->sound_file = eina_stringshare_add(val);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "sound-name"))
|
||||||
|
{
|
||||||
|
const char *val = NULL;
|
||||||
|
|
||||||
|
eldbus_message_iter_arguments_get(var, "s", &val);
|
||||||
|
printf("NOT: sound-file=[%s]\n", val);
|
||||||
|
// sound naming spec to play
|
||||||
|
// http://0pointer.de/public/sound-naming-spec.html
|
||||||
|
if (val) n->sound_name = eina_stringshare_add(val);
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "transient"))
|
||||||
|
{
|
||||||
|
Eina_Bool val = 0;
|
||||||
|
|
||||||
|
eldbus_message_iter_arguments_get(var, "b", &val);
|
||||||
|
printf("NOT: transient=%i\n", val);
|
||||||
|
n->transient = val;
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "x"))
|
||||||
|
{
|
||||||
|
int val = 0;
|
||||||
|
|
||||||
|
eldbus_message_iter_arguments_get(var, "i", &val);
|
||||||
|
printf("NOT: x=%i\n", val);
|
||||||
|
n->x = val;
|
||||||
|
n->have_xy = EINA_TRUE;
|
||||||
|
}
|
||||||
|
else if (!strcmp(key, "y"))
|
||||||
|
{
|
||||||
|
int val = 0;
|
||||||
|
|
||||||
|
eldbus_message_iter_arguments_get(var, "i", &val);
|
||||||
|
printf("NOT: y=%i\n", val);
|
||||||
|
n->y = val;
|
||||||
|
n->have_xy = EINA_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* this function should be external in edje for use in cases such as this module.
|
/* this function should be external in edje for use in cases such as this module.
|
||||||
*
|
*
|
||||||
* happily, it was decided that the function would not be external so that it could
|
* happily, it was decided that the function would not be external so that it could
|
||||||
|
@ -93,134 +223,188 @@ _text_escape(Eina_Strbuf *txt, const char *text)
|
||||||
return advance;
|
return advance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hardcoded list of allowed tags based on
|
static int
|
||||||
* https://people.gnome.org/~mccann/docs/notification-spec/notification-spec-latest.html#markup
|
_tag_len(const char *txt)
|
||||||
*/
|
|
||||||
static const char *tags[] =
|
|
||||||
{
|
{
|
||||||
"<b",
|
const char *s;
|
||||||
"<i",
|
Eina_Bool backslash = EINA_FALSE;
|
||||||
"<u",
|
Eina_Bool inquote = EINA_FALSE, indblquote = EINA_FALSE;
|
||||||
//"<a", FIXME: we can't actually display these right now
|
|
||||||
//"<img",
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *
|
if (txt[0] != '<') return 0;
|
||||||
_get_tag(const char *c)
|
for (s = txt; *s; s++)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
if (!backslash)
|
||||||
|
{
|
||||||
if (c[1] != '>') return NULL;
|
if (*s == '\\') backslash = EINA_TRUE;
|
||||||
for (i = 0; i < EINA_C_ARRAY_LENGTH(tags); i++)
|
else
|
||||||
if (tags[i][1] == c[0]) return tags[i];
|
{
|
||||||
return NULL;
|
if (inquote)
|
||||||
|
{
|
||||||
|
if (*s == '\'') inquote = EINA_FALSE;
|
||||||
|
}
|
||||||
|
else if (indblquote)
|
||||||
|
{
|
||||||
|
if (*s == '"') indblquote = EINA_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*s == '>')
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (*s == '\'') inquote = EINA_TRUE;
|
||||||
|
else if (*s == '\"') indblquote = EINA_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else backslash = EINA_FALSE;
|
||||||
|
}
|
||||||
|
return s - txt;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
static char *
|
||||||
|
_path_get(const char *txt)
|
||||||
|
{
|
||||||
|
Eina_Strbuf *buf;
|
||||||
|
char *ret;
|
||||||
|
const char *s;
|
||||||
|
Eina_Bool backslash = EINA_FALSE;
|
||||||
|
Eina_Bool inquote = EINA_FALSE, indblquote = EINA_FALSE;
|
||||||
|
|
||||||
|
if (txt[0] == '>') return NULL;
|
||||||
|
|
||||||
|
buf = eina_strbuf_new();
|
||||||
|
if (!buf) return NULL;
|
||||||
|
|
||||||
|
for (s = txt; *s; s++)
|
||||||
|
{
|
||||||
|
if (!backslash)
|
||||||
|
{
|
||||||
|
if (*s == '\\') backslash = EINA_TRUE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (inquote)
|
||||||
|
{
|
||||||
|
if (*s == '\'') inquote = EINA_FALSE;
|
||||||
|
else eina_strbuf_append_char(buf, *s);
|
||||||
|
}
|
||||||
|
else if (indblquote)
|
||||||
|
{
|
||||||
|
if (*s == '"') indblquote = EINA_FALSE;
|
||||||
|
else eina_strbuf_append_char(buf, *s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*s == '>') break;
|
||||||
|
else if (*s == ' ') break;
|
||||||
|
else if (*s == '\'') inquote = EINA_TRUE;
|
||||||
|
else if (*s == '\"') indblquote = EINA_TRUE;
|
||||||
|
else eina_strbuf_append_char(buf, *s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eina_strbuf_append_char(buf, *s);
|
||||||
|
backslash = EINA_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = eina_strbuf_string_steal(buf);
|
||||||
|
eina_strbuf_free(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
_nedje_text_escape(const char *text)
|
_nedje_text_escape(const char *text)
|
||||||
{
|
{
|
||||||
Eina_Strbuf *txt;
|
Eina_Strbuf *txt;
|
||||||
char *ret;
|
char *ret;
|
||||||
const char *text_end;
|
const char *text_end;
|
||||||
size_t text_len;
|
int taglen;
|
||||||
Eina_Array *arr;
|
|
||||||
const char *cur_tag = NULL;
|
|
||||||
|
|
||||||
if (!text) return NULL;
|
if (!text) return NULL;
|
||||||
|
|
||||||
txt = eina_strbuf_new();
|
txt = eina_strbuf_new();
|
||||||
text_len = strlen(text);
|
if (!txt) return NULL;
|
||||||
arr = eina_array_new(3);
|
|
||||||
|
text_end = text + strlen(text);
|
||||||
|
|
||||||
text_end = text + text_len;
|
|
||||||
while (text < text_end)
|
while (text < text_end)
|
||||||
{
|
{
|
||||||
int advance;
|
taglen = _tag_len(text);
|
||||||
|
if (taglen == 0)
|
||||||
if ((text[0] == '<') && text[1])
|
|
||||||
{
|
{
|
||||||
const char *tag, *popped;
|
eina_strbuf_append_char(txt, text[0]);
|
||||||
Eina_Bool closing = EINA_FALSE;
|
text++;
|
||||||
|
|
||||||
if (text[1] == '/') //closing tag
|
|
||||||
{
|
|
||||||
closing = EINA_TRUE;
|
|
||||||
tag = _get_tag(text + 2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tag = _get_tag(text + 1);
|
|
||||||
if (closing)
|
|
||||||
{
|
|
||||||
if (cur_tag && (tag != cur_tag))
|
|
||||||
{
|
|
||||||
/* tag mismatch: autoclose all failure tags
|
|
||||||
* not technically required by the spec,
|
|
||||||
* but it makes me feel better about myself
|
|
||||||
*/
|
|
||||||
do
|
|
||||||
{
|
|
||||||
popped = eina_array_pop(arr);
|
|
||||||
if (eina_array_count(arr))
|
|
||||||
cur_tag = eina_array_data_get(arr, eina_array_count(arr) - 1);
|
|
||||||
else
|
|
||||||
cur_tag = NULL;
|
|
||||||
eina_strbuf_append_printf(txt, "</%c>", popped[1]);
|
|
||||||
} while (cur_tag && (popped != tag));
|
|
||||||
advance = 4;
|
|
||||||
}
|
|
||||||
else if (cur_tag)
|
|
||||||
{
|
|
||||||
/* tag match: just pop */
|
|
||||||
popped = eina_array_pop(arr);
|
|
||||||
if (eina_array_count(arr))
|
|
||||||
cur_tag = eina_array_data_get(arr, eina_array_count(arr) - 1);
|
|
||||||
else
|
|
||||||
cur_tag = NULL;
|
|
||||||
eina_strbuf_append_printf(txt, "</%c>", popped[1]);
|
|
||||||
advance = 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* no current tag: escape */
|
|
||||||
advance = _text_escape(txt, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (tag)
|
|
||||||
{
|
|
||||||
cur_tag = tag;
|
|
||||||
eina_array_push(arr, tag);
|
|
||||||
eina_strbuf_append_printf(txt, "<%c>", tag[1]);
|
|
||||||
advance = 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
advance = _text_escape(txt, text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (text[0] == '&')
|
|
||||||
{
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
s = strchr(text, ';');
|
|
||||||
if (s)
|
|
||||||
s = evas_textblock_escape_string_range_get(text, s + 1);
|
|
||||||
if (s)
|
|
||||||
{
|
|
||||||
eina_strbuf_append_char(txt, text[0]);
|
|
||||||
advance = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
advance = _text_escape(txt, text);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
advance = _text_escape(txt, text);
|
{
|
||||||
|
if (!strncmp(text, "<b>", 3)) eina_strbuf_append(txt, "<b>");
|
||||||
|
else if (!strncmp(text, "</b>", 4)) eina_strbuf_append(txt, "</b>");
|
||||||
|
else if (!strncmp(text, "<i>", 3)) eina_strbuf_append(txt, "<i>");
|
||||||
|
else if (!strncmp(text, "</i>", 4)) eina_strbuf_append(txt, "</i>");
|
||||||
|
else if (!strncmp(text, "<u>", 3)) eina_strbuf_append(txt, "<u>");
|
||||||
|
else if (!strncmp(text, "</u>", 4)) eina_strbuf_append(txt, "</u>");
|
||||||
|
else if (!strncmp(text, "<a ", 3))
|
||||||
|
{
|
||||||
|
eina_strbuf_append(txt, "<link>");
|
||||||
|
eina_strbuf_append_n(txt, text, taglen);
|
||||||
|
}
|
||||||
|
else if (!strncmp(text, "</a>", 3))
|
||||||
|
{
|
||||||
|
eina_strbuf_append(txt, "</a></link>");
|
||||||
|
}
|
||||||
|
else if (!strncmp(text, "<img src=", 9))
|
||||||
|
{
|
||||||
|
Evas_Object *o;
|
||||||
|
int w = 0, h = 0;
|
||||||
|
char *path;
|
||||||
|
|
||||||
text += advance;
|
path = _path_get(text + 9);
|
||||||
|
if ((path) && (strlen(path) > 0))
|
||||||
|
{
|
||||||
|
o = evas_object_image_add(e_comp->evas);
|
||||||
|
evas_object_image_file_set(o, path, NULL);
|
||||||
|
evas_object_image_size_get(o, &w, &h);
|
||||||
|
printf("NOT: imgpath=%s %ix%i\n", path, w, h);
|
||||||
|
if ((w > 0) && (h > 0))
|
||||||
|
{
|
||||||
|
double neww = w, newh = h;
|
||||||
|
|
||||||
|
if (neww > 200.0)
|
||||||
|
{
|
||||||
|
double oldw = neww;
|
||||||
|
|
||||||
|
neww = 200.0;
|
||||||
|
newh = (newh * neww) / oldw;
|
||||||
|
}
|
||||||
|
if (newh > 100.0)
|
||||||
|
{
|
||||||
|
double oldh = newh;
|
||||||
|
|
||||||
|
newh = 100.0;
|
||||||
|
neww = (neww * newh) / oldh;
|
||||||
|
}
|
||||||
|
neww *= e_scale;
|
||||||
|
newh *= e_scale;
|
||||||
|
w = neww + 0.5;
|
||||||
|
h = newh + 0.5;
|
||||||
|
eina_strbuf_append_printf
|
||||||
|
(txt, "<item absize=%ix%i href=", w, h);
|
||||||
|
eina_strbuf_append_n(txt, text + 9, taglen - 9);
|
||||||
|
eina_strbuf_append(txt, "</item>");
|
||||||
|
}
|
||||||
|
evas_object_del(o);
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
text += taglen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eina_array_free(arr);
|
|
||||||
ret = eina_strbuf_string_steal(txt);
|
ret = eina_strbuf_string_steal(txt);
|
||||||
|
printf("NOT: body -> [%s]\n", ret);
|
||||||
eina_strbuf_free(txt);
|
eina_strbuf_free(txt);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -231,28 +415,30 @@ notify_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Messag
|
||||||
E_Notification_Notify *n;
|
E_Notification_Notify *n;
|
||||||
Eldbus_Message_Iter *actions_iter, *hints_iter;
|
Eldbus_Message_Iter *actions_iter, *hints_iter;
|
||||||
Eldbus_Message *reply;
|
Eldbus_Message *reply;
|
||||||
char *txt;
|
char *txt, *txt2;
|
||||||
|
int num;
|
||||||
|
|
||||||
if (!n_data->notify_cb)
|
if (!n_data->notify_cb) return NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
n = E_OBJECT_ALLOC(E_Notification_Notify, E_NOTIFICATION_TYPE, _notification_free);
|
n = E_OBJECT_ALLOC(E_Notification_Notify, E_NOTIFICATION_TYPE, _notification_free);
|
||||||
n->urgency = E_NOTIFICATION_NOTIFY_URGENCY_NORMAL;
|
n->urgency = E_NOTIFICATION_NOTIFY_URGENCY_NORMAL;
|
||||||
if (!eldbus_message_arguments_get(msg, "susssasa{sv}i", &n->app_name,
|
if (!eldbus_message_arguments_get(msg, "susssasa{sv}i",
|
||||||
&n->replaces_id, &n->icon.icon, &n->summary,
|
&n->app_name, &n->replaces_id,
|
||||||
&n->body, &actions_iter, &hints_iter,
|
&n->icon.icon, &n->summary, &n->body,
|
||||||
&n->timeout))
|
&actions_iter, &hints_iter, &n->timeout))
|
||||||
{
|
{
|
||||||
ERR("Reading message.");
|
ERR("Reading message.");
|
||||||
e_object_del(E_OBJECT(n));
|
e_object_del(E_OBJECT(n));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (e_screensaver_on_get() && e_config->screensaver_wake_on_notify)
|
if (e_screensaver_on_get() && e_config->screensaver_wake_on_notify)
|
||||||
{
|
{ // XXX: this is an attempt to wake the screen? should be an option
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
|
ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
|
||||||
ecore_evas_pointer_warp(e_comp->ee, x, y);
|
ecore_evas_pointer_warp(e_comp->ee, x, y);
|
||||||
}
|
}
|
||||||
|
// walk hints
|
||||||
eldbus_message_iter_dict_iterate(hints_iter, "sv", hints_dict_iter, n);
|
eldbus_message_iter_dict_iterate(hints_iter, "sv", hints_dict_iter, n);
|
||||||
n->app_name = eina_stringshare_add(n->app_name);
|
n->app_name = eina_stringshare_add(n->app_name);
|
||||||
n->icon.icon = eina_stringshare_add(n->icon.icon);
|
n->icon.icon = eina_stringshare_add(n->icon.icon);
|
||||||
|
@ -261,22 +447,43 @@ notify_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Messag
|
||||||
n->body = eina_stringshare_add(txt);
|
n->body = eina_stringshare_add(txt);
|
||||||
free(txt);
|
free(txt);
|
||||||
|
|
||||||
|
num = 0;
|
||||||
|
while (eldbus_message_iter_get_and_next(actions_iter, 's', &txt))
|
||||||
|
{
|
||||||
|
if (eldbus_message_iter_get_and_next(actions_iter, 's', &txt2))
|
||||||
|
{ // XXX: add actions to notification
|
||||||
|
E_Notification_Notify_Action *actions;
|
||||||
|
|
||||||
|
printf("NOT: act=[%s] [%s]\n", txt, txt2);
|
||||||
|
num++;
|
||||||
|
actions = realloc(n->actions, (num + 1) * sizeof(E_Notification_Notify));
|
||||||
|
if (actions)
|
||||||
|
{
|
||||||
|
n->actions = actions;
|
||||||
|
n->actions[num - 1].action = eina_stringshare_add(txt);
|
||||||
|
n->actions[num - 1].label = eina_stringshare_add(txt2);
|
||||||
|
n->actions[num].action = NULL;
|
||||||
|
n->actions[num].label = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
e_object_ref(E_OBJECT(n));
|
e_object_ref(E_OBJECT(n));
|
||||||
n->id = n_data->notify_cb(n_data->data, n);
|
n->id = n_data->notify_cb(n_data->data, n);
|
||||||
reply = eldbus_message_method_return_new(msg);
|
reply = eldbus_message_method_return_new(msg);
|
||||||
eldbus_message_arguments_append(reply, "u", n->id);
|
eldbus_message_arguments_append(reply, "u", n->id);
|
||||||
e_object_unref(E_OBJECT(n));
|
e_object_unref(E_OBJECT(n));
|
||||||
|
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eldbus_Message *
|
static Eldbus_Message *
|
||||||
close_notification_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
|
close_notification_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
|
||||||
{
|
{
|
||||||
unsigned id;
|
unsigned int id;
|
||||||
if (!eldbus_message_arguments_get(msg, "u", &id))
|
|
||||||
return NULL;
|
if (!eldbus_message_arguments_get(msg, "u", &id)) return NULL;
|
||||||
if (n_data->close_cb)
|
if (n_data->close_cb) n_data->close_cb(n_data->data, id);
|
||||||
n_data->close_cb(n_data->data, id);
|
|
||||||
return eldbus_message_method_return_new(msg);
|
return eldbus_message_method_return_new(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,8 +498,10 @@ capabilities_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_
|
||||||
eldbus_message_iter_arguments_append(main_iter, "as", &array);
|
eldbus_message_iter_arguments_append(main_iter, "as", &array);
|
||||||
|
|
||||||
for (i = 0; n_data->server_info->capabilities[i]; i++)
|
for (i = 0; n_data->server_info->capabilities[i]; i++)
|
||||||
eldbus_message_iter_arguments_append(array, "s",
|
{
|
||||||
n_data->server_info->capabilities[i]);
|
eldbus_message_iter_arguments_append
|
||||||
|
(array, "s", n_data->server_info->capabilities[i]);
|
||||||
|
}
|
||||||
eldbus_message_iter_container_close(main_iter, array);
|
eldbus_message_iter_container_close(main_iter, array);
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
@ -301,23 +510,32 @@ static Eldbus_Message *
|
||||||
server_info_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
|
server_info_cb(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
|
||||||
{
|
{
|
||||||
Eldbus_Message *reply = eldbus_message_method_return_new(msg);
|
Eldbus_Message *reply = eldbus_message_method_return_new(msg);
|
||||||
eldbus_message_arguments_append(reply, "ssss", n_data->server_info->name,
|
eldbus_message_arguments_append(reply, "ssss",
|
||||||
n_data->server_info->vendor,
|
n_data->server_info->name,
|
||||||
n_data->server_info->version,
|
n_data->server_info->vendor,
|
||||||
n_data->server_info->spec_version);
|
n_data->server_info->version,
|
||||||
|
n_data->server_info->spec_version);
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Eldbus_Method methods[] = {
|
static const Eldbus_Method methods[] = {
|
||||||
{ "Notify",
|
{ "Notify",
|
||||||
ELDBUS_ARGS({"s", "app_name"}, {"u", "replaces_id"}, {"s", "app_icon"}, {"s", "summary"}, {"s", "body"}, {"as", "actions"}, {"a{sv}", "hints"}, {"i", "expire_timeout"}),
|
ELDBUS_ARGS({"s", "app_name"}, {"u", "replaces_id"}, {"s", "app_icon"}, {"s", "summary"}, {"s", "body"}, {"as", "actions"}, {"a{sv}", "hints"}, {"i", "expire_timeout"}),
|
||||||
ELDBUS_ARGS({"u", "id"}), notify_cb, 0 },
|
ELDBUS_ARGS({"u", "id"}),
|
||||||
{ "CloseNotification", ELDBUS_ARGS({"u", "id"}), NULL, close_notification_cb, 0 },
|
notify_cb, 0 },
|
||||||
{ "GetCapabilities", NULL, ELDBUS_ARGS({"as", "capabilities"}),
|
{ "CloseNotification",
|
||||||
capabilities_cb, 0 },
|
ELDBUS_ARGS({"u", "id"}),
|
||||||
{ "GetServerInformation", NULL,
|
NULL,
|
||||||
ELDBUS_ARGS({"s", "name"}, {"s", "vendor"}, {"s", "version"}, {"s", "spec_version"}),
|
close_notification_cb, 0 },
|
||||||
server_info_cb, 0 },
|
{ "GetCapabilities",
|
||||||
|
NULL,
|
||||||
|
ELDBUS_ARGS({"as", "capabilities"}),
|
||||||
|
capabilities_cb, 0 },
|
||||||
|
{ "GetServerInformation",
|
||||||
|
NULL,
|
||||||
|
ELDBUS_ARGS({"s", "name"}, {"s", "vendor"}, {"s", "version"}, {"s", "spec_version"}),
|
||||||
|
server_info_cb, 0 },
|
||||||
|
|
||||||
{ NULL, NULL, NULL, NULL, 0 }
|
{ NULL, NULL, NULL, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -332,6 +550,7 @@ static const Eldbus_Signal signals[] = {
|
||||||
{ "NotificationClosed", ELDBUS_ARGS({"u", "id"}, {"u", "reason"}), 0 },
|
{ "NotificationClosed", ELDBUS_ARGS({"u", "id"}, {"u", "reason"}), 0 },
|
||||||
[SIGNAL_ACTION_INVOKED] =
|
[SIGNAL_ACTION_INVOKED] =
|
||||||
{ "ActionInvoked", ELDBUS_ARGS({"u", "id"}, {"s", "action_key"}), 0 },
|
{ "ActionInvoked", ELDBUS_ARGS({"u", "id"}, {"s", "action_key"}), 0 },
|
||||||
|
|
||||||
{ NULL, NULL, 0}
|
{ NULL, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -347,8 +566,8 @@ E_API Eina_Bool
|
||||||
e_notification_server_register(const E_Notification_Server_Info *server_info, E_Notification_Notify_Cb n_cb, E_Notification_Close_Cb close_cb, const void *data)
|
e_notification_server_register(const E_Notification_Server_Info *server_info, E_Notification_Notify_Cb n_cb, E_Notification_Close_Cb close_cb, const void *data)
|
||||||
{
|
{
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(server_info, EINA_FALSE);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(server_info, EINA_FALSE);
|
||||||
if (n_data)
|
|
||||||
return EINA_FALSE;
|
if (n_data) return EINA_FALSE;
|
||||||
n_data = calloc(1, sizeof(Notification_Data));
|
n_data = calloc(1, sizeof(Notification_Data));
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(n_data, EINA_FALSE);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(n_data, EINA_FALSE);
|
||||||
|
|
||||||
|
@ -359,8 +578,7 @@ e_notification_server_register(const E_Notification_Server_Info *server_info, E_
|
||||||
n_data->data = (void *)data;
|
n_data->data = (void *)data;
|
||||||
n_data->server_info = server_info;
|
n_data->server_info = server_info;
|
||||||
eldbus_name_request(n_data->conn, BUS,
|
eldbus_name_request(n_data->conn, BUS,
|
||||||
ELDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING, NULL, NULL);
|
ELDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING, NULL, NULL);
|
||||||
|
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,7 +599,17 @@ e_notification_notify_close(E_Notification_Notify *notify, E_Notification_Notify
|
||||||
EINA_SAFETY_ON_NULL_RETURN(notify);
|
EINA_SAFETY_ON_NULL_RETURN(notify);
|
||||||
EINA_SAFETY_ON_FALSE_RETURN(reason <= E_NOTIFICATION_NOTIFY_CLOSED_REASON_UNDEFINED);
|
EINA_SAFETY_ON_FALSE_RETURN(reason <= E_NOTIFICATION_NOTIFY_CLOSED_REASON_UNDEFINED);
|
||||||
eldbus_service_signal_emit(n_data->iface, SIGNAL_NOTIFICATION_CLOSED,
|
eldbus_service_signal_emit(n_data->iface, SIGNAL_NOTIFICATION_CLOSED,
|
||||||
notify->id, reason);
|
notify->id, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
E_API void
|
||||||
|
e_notification_notify_action(E_Notification_Notify *notify, const char *action)
|
||||||
|
{
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(n_data);
|
||||||
|
EINA_SAFETY_ON_NULL_RETURN(notify);
|
||||||
|
if (!action) action = "";
|
||||||
|
eldbus_service_signal_emit(n_data->iface, SIGNAL_ACTION_INVOKED,
|
||||||
|
notify->id, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
E_API Evas_Object *
|
E_API Evas_Object *
|
||||||
|
@ -491,6 +719,7 @@ notification_client_dbus_send(E_Notification_Notify *notify, E_Notification_Clie
|
||||||
{
|
{
|
||||||
Eldbus_Message_Iter *st, *data_iter;
|
Eldbus_Message_Iter *st, *data_iter;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
eldbus_message_iter_arguments_append(hints, "{sv}", &entry);
|
eldbus_message_iter_arguments_append(hints, "{sv}", &entry);
|
||||||
eldbus_message_iter_arguments_append(entry, "s", "image-data");
|
eldbus_message_iter_arguments_append(entry, "s", "image-data");
|
||||||
var = eldbus_message_iter_container_new(entry, 'v', "(iiibiiay)");
|
var = eldbus_message_iter_container_new(entry, 'v', "(iiibiiay)");
|
||||||
|
@ -533,8 +762,7 @@ notification_client_dbus_send(E_Notification_Notify *notify, E_Notification_Clie
|
||||||
|
|
||||||
p = eldbus_connection_send(conn, msg, client_notify_cb, data, 5000);
|
p = eldbus_connection_send(conn, msg, client_notify_cb, data, 5000);
|
||||||
EINA_SAFETY_ON_NULL_GOTO(p, error);
|
EINA_SAFETY_ON_NULL_GOTO(p, error);
|
||||||
if (cb)
|
if (cb) eldbus_pending_data_set(p, "cb", cb);
|
||||||
eldbus_pending_data_set(p, "cb", cb);
|
|
||||||
eldbus_pending_data_set(p, "conn", conn);
|
eldbus_pending_data_set(p, "conn", conn);
|
||||||
|
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
|
@ -547,8 +775,7 @@ error:
|
||||||
static void
|
static void
|
||||||
normalize_notify(E_Notification_Notify *notify)
|
normalize_notify(E_Notification_Notify *notify)
|
||||||
{
|
{
|
||||||
if (!notify->timeout)
|
if (!notify->timeout) notify->timeout = -1;
|
||||||
notify->timeout = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
E_API Eina_Bool
|
E_API Eina_Bool
|
||||||
|
@ -562,11 +789,12 @@ e_notification_client_send(E_Notification_Notify *notify, E_Notification_Client_
|
||||||
|
|
||||||
if (!n_data)
|
if (!n_data)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "UNHANDLED NOTIFICATION:\nSummary: %s\nBody: %s\n", notify->summary, notify->body);
|
fprintf(stderr, "UNHANDLED NOTIFICATION:\nSummary: %s\nBody: %s\n",
|
||||||
|
notify->summary, notify->body);
|
||||||
return notification_client_dbus_send(notify, cb, data);
|
return notification_client_dbus_send(notify, cb, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
//local
|
// local
|
||||||
copy = malloc(sizeof(E_Notification_Notify));
|
copy = malloc(sizeof(E_Notification_Notify));
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(copy, EINA_FALSE);
|
||||||
memcpy(copy, notify, sizeof(E_Notification_Notify));
|
memcpy(copy, notify, sizeof(E_Notification_Notify));
|
||||||
|
@ -579,8 +807,7 @@ e_notification_client_send(E_Notification_Notify *notify, E_Notification_Client_
|
||||||
copy->icon.icon_path = eina_stringshare_add(notify->icon.icon_path);
|
copy->icon.icon_path = eina_stringshare_add(notify->icon.icon_path);
|
||||||
|
|
||||||
id = n_data->notify_cb(n_data->data, copy);
|
id = n_data->notify_cb(n_data->data, copy);
|
||||||
if (cb)
|
if (cb) cb((void *)data, id);
|
||||||
cb((void *)data, id);
|
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,35 +7,39 @@
|
||||||
|
|
||||||
typedef enum _E_Notification_Notify_Urgency
|
typedef enum _E_Notification_Notify_Urgency
|
||||||
{
|
{
|
||||||
E_NOTIFICATION_NOTIFY_URGENCY_LOW,
|
E_NOTIFICATION_NOTIFY_URGENCY_LOW = 0,
|
||||||
E_NOTIFICATION_NOTIFY_URGENCY_NORMAL,
|
E_NOTIFICATION_NOTIFY_URGENCY_NORMAL = 1,
|
||||||
E_NOTIFICATION_NOTIFY_URGENCY_CRITICAL
|
E_NOTIFICATION_NOTIFY_URGENCY_CRITICAL = 2
|
||||||
} E_Notification_Notify_Urgency;
|
} E_Notification_Notify_Urgency;
|
||||||
|
|
||||||
typedef enum _E_Notification_Notify_Closed_Reason
|
typedef enum _E_Notification_Notify_Closed_Reason
|
||||||
{
|
{
|
||||||
E_NOTIFICATION_NOTIFY_CLOSED_REASON_EXPIRED, /** The notification expired. */
|
E_NOTIFICATION_NOTIFY_CLOSED_REASON_EXPIRED = 1,
|
||||||
E_NOTIFICATION_NOTIFY_CLOSED_REASON_DISMISSED, /** The notification was dismissed by the user. */
|
E_NOTIFICATION_NOTIFY_CLOSED_REASON_DISMISSED = 2,
|
||||||
E_NOTIFICATION_NOTIFY_CLOSED_REASON_REQUESTED, /** The notification was closed by a call to CloseNotification method. */
|
E_NOTIFICATION_NOTIFY_CLOSED_REASON_REQUESTED = 3,
|
||||||
E_NOTIFICATION_NOTIFY_CLOSED_REASON_UNDEFINED /** Undefined/reserved reasons. */
|
E_NOTIFICATION_NOTIFY_CLOSED_REASON_UNDEFINED = 4
|
||||||
} E_Notification_Notify_Closed_Reason;
|
} E_Notification_Notify_Closed_Reason;
|
||||||
|
|
||||||
|
typedef struct _E_Notification_Notify_Action
|
||||||
|
{
|
||||||
|
const char *action;
|
||||||
|
const char *label;
|
||||||
|
} E_Notification_Notify_Action;
|
||||||
|
|
||||||
typedef struct _E_Notification_Notify
|
typedef struct _E_Notification_Notify
|
||||||
{
|
{
|
||||||
E_Object e_obj_inherit;
|
E_Object e_obj_inherit;
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
const char *app_name;
|
const char *app_name;
|
||||||
unsigned replaces_id;
|
unsigned int replaces_id;
|
||||||
const char *summary;
|
const char *summary;
|
||||||
const char *body;
|
const char *body;
|
||||||
int timeout;
|
int timeout; // time in ms
|
||||||
E_Notification_Notify_Urgency urgency;
|
E_Notification_Notify_Urgency urgency;
|
||||||
struct
|
struct {
|
||||||
{
|
|
||||||
const char *icon;
|
const char *icon;
|
||||||
const char *icon_path;
|
const char *icon_path;
|
||||||
struct
|
struct {
|
||||||
{
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
int rowstride;
|
int rowstride;
|
||||||
|
@ -46,6 +50,17 @@ typedef struct _E_Notification_Notify
|
||||||
int data_size;
|
int data_size;
|
||||||
} raw;
|
} raw;
|
||||||
} icon;
|
} icon;
|
||||||
|
const char *category;
|
||||||
|
const char *desktop_entry;
|
||||||
|
const char *sound_file;
|
||||||
|
const char *sound_name;
|
||||||
|
int x, y;
|
||||||
|
Eina_Bool have_xy;
|
||||||
|
Eina_Bool icon_actions;
|
||||||
|
Eina_Bool resident;
|
||||||
|
Eina_Bool suppress_sound;
|
||||||
|
Eina_Bool transient;
|
||||||
|
E_Notification_Notify_Action *actions;
|
||||||
} E_Notification_Notify;
|
} E_Notification_Notify;
|
||||||
|
|
||||||
typedef unsigned int (*E_Notification_Notify_Cb)(void *data, E_Notification_Notify *n);
|
typedef unsigned int (*E_Notification_Notify_Cb)(void *data, E_Notification_Notify *n);
|
||||||
|
@ -80,7 +95,9 @@ E_API Evas_Object *e_notification_notify_raw_image_get(E_Notification_Notify *no
|
||||||
|
|
||||||
//client
|
//client
|
||||||
typedef void (*E_Notification_Client_Send_Cb)(void *data, unsigned int id);
|
typedef void (*E_Notification_Client_Send_Cb)(void *data, unsigned int id);
|
||||||
|
|
||||||
E_API Eina_Bool e_notification_client_send(E_Notification_Notify *notify, E_Notification_Client_Send_Cb cb, const void *data);
|
E_API Eina_Bool e_notification_client_send(E_Notification_Notify *notify, E_Notification_Client_Send_Cb cb, const void *data);
|
||||||
|
E_API void e_notification_notify_action(E_Notification_Notify *notify, const char *action);
|
||||||
E_API Eina_Bool e_notification_util_send(const char *summary, const char *body);
|
E_API Eina_Bool e_notification_util_send(const char *summary, const char *body);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,20 @@ _notification_notify(E_Notification_Notify *n)
|
||||||
E_API E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Notification"};
|
E_API E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Notification"};
|
||||||
|
|
||||||
static const E_Notification_Server_Info server_info = {
|
static const E_Notification_Server_Info server_info = {
|
||||||
.name = "e17",
|
.name = "Notification Service",
|
||||||
.vendor = "enlightenment.org",
|
.vendor = "Enlightenment",
|
||||||
.version = "0.17",
|
.version = PACKAGE_VERSION,
|
||||||
.spec_version = "1.2",
|
.spec_version = "1.2",
|
||||||
.capabilities = { "body", "body-markup", NULL }
|
.capabilities = {
|
||||||
|
"body", "body-markup",
|
||||||
|
"body-hyperlinks", "body-images",
|
||||||
|
"actions", "action-icons",
|
||||||
|
// "icon-multi",
|
||||||
|
// or
|
||||||
|
// "icon-static",
|
||||||
|
"persistence",
|
||||||
|
// "sound",
|
||||||
|
NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Callbacks */
|
/* Callbacks */
|
||||||
|
|
|
@ -31,34 +31,37 @@ typedef enum
|
||||||
|
|
||||||
struct _Config
|
struct _Config
|
||||||
{
|
{
|
||||||
E_Config_Dialog *cfd;
|
E_Config_Dialog *cfd;
|
||||||
|
|
||||||
int version;
|
int version;
|
||||||
int show_low;
|
int show_low;
|
||||||
int show_normal;
|
int show_normal;
|
||||||
int show_critical;
|
int show_critical;
|
||||||
int force_timeout;
|
int force_timeout;
|
||||||
int ignore_replacement;
|
int ignore_replacement;
|
||||||
Popup_Display_Policy dual_screen;
|
Popup_Display_Policy dual_screen;
|
||||||
float timeout;
|
float timeout;
|
||||||
Popup_Corner corner;
|
Popup_Corner corner;
|
||||||
|
|
||||||
Eina_List *popups;
|
Eina_List *popups;
|
||||||
unsigned int next_id;
|
unsigned int next_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Popup_Data
|
struct _Popup_Data
|
||||||
{
|
{
|
||||||
unsigned id;
|
unsigned id;
|
||||||
E_Notification_Notify *notif;
|
E_Notification_Notify *notif;
|
||||||
Evas_Object *win;
|
Evas_Object *win;
|
||||||
Eina_List *mirrors;
|
Eina_List *mirrors;
|
||||||
Evas *e;
|
Evas *e;
|
||||||
Evas_Object *theme;
|
Evas_Object *theme;
|
||||||
const char *app_name;
|
const char *app_name;
|
||||||
Evas_Object *app_icon;
|
Evas_Object *app_icon;
|
||||||
Ecore_Timer *timer;
|
Evas_Object *desktop_icon;
|
||||||
Eina_Bool pending E_BITFIELD;
|
Evas_Object *action_box;
|
||||||
|
Eina_List *actions;
|
||||||
|
Ecore_Timer *timer;
|
||||||
|
Eina_Bool pending E_BITFIELD;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -239,6 +239,61 @@ _notification_theme_cb_find(Popup_Data *popup,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_notification_theme_cb_anchor(Popup_Data *popup EINA_UNUSED,
|
||||||
|
Evas_Object *obj EINA_UNUSED,
|
||||||
|
const char *emission,
|
||||||
|
const char *source EINA_UNUSED)
|
||||||
|
{
|
||||||
|
if (!strncmp(emission, "anchor,mouse,clicked,1,",
|
||||||
|
strlen("anchor,mouse,clicked,1,")))
|
||||||
|
{
|
||||||
|
const char *href = emission + strlen("anchor,mouse,clicked,1,");
|
||||||
|
Eina_Strbuf *buf = eina_strbuf_new();
|
||||||
|
|
||||||
|
if (buf)
|
||||||
|
{
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
eina_strbuf_append(buf, href);
|
||||||
|
s = eina_strbuf_string_get(buf);
|
||||||
|
if ((s) && (*s == '"'))
|
||||||
|
{
|
||||||
|
eina_strbuf_remove(buf, 0, 1);
|
||||||
|
s = eina_strbuf_string_get(buf);
|
||||||
|
if ((s) && (strlen(s) > 0) && (s[strlen(s) - 1] == '"'))
|
||||||
|
eina_strbuf_replace_last(buf, "\"", "");
|
||||||
|
}
|
||||||
|
if ((s) && (*s == '\''))
|
||||||
|
{
|
||||||
|
eina_strbuf_remove(buf, 0, 1);
|
||||||
|
s = eina_strbuf_string_get(buf);
|
||||||
|
if ((s) && (strlen(s) > 0) && (s[strlen(s) - 1] == '\''))
|
||||||
|
eina_strbuf_replace_last(buf, "'", "");
|
||||||
|
}
|
||||||
|
printf("NOT: clicked=[%s]\n", eina_strbuf_string_get(buf));
|
||||||
|
e_util_open(eina_strbuf_string_get(buf), NULL);
|
||||||
|
eina_strbuf_free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_notification_theme_cb_action(Popup_Data *popup,
|
||||||
|
Evas_Object *obj,
|
||||||
|
const char *emission EINA_UNUSED,
|
||||||
|
const char *source EINA_UNUSED)
|
||||||
|
{
|
||||||
|
const char *action = evas_object_data_get(obj, "action");
|
||||||
|
|
||||||
|
if (action)
|
||||||
|
{
|
||||||
|
printf("NOT: action=[%s]\n", action);
|
||||||
|
e_notification_notify_action(popup->notif, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_notification_popup_place_coords_get(int zw, int zh, int ow, int oh, int pos, int *x, int *y)
|
_notification_popup_place_coords_get(int zw, int zh, int ow, int oh, int pos, int *x, int *y)
|
||||||
{
|
{
|
||||||
|
@ -269,6 +324,22 @@ _notification_popup_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EIN
|
||||||
popup->win = NULL;
|
popup->win = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Evas_Object *
|
||||||
|
_cb_item_provider(void *data, Evas_Object *obj EINA_UNUSED, const char *part, const char *item)
|
||||||
|
{
|
||||||
|
Popup_Data *popup = data;
|
||||||
|
|
||||||
|
printf("NOT: PROVIDER.... [%s] item: [%s]\n", part, item);
|
||||||
|
// if (!strcmp(part, "notification.textblock.message"))
|
||||||
|
{
|
||||||
|
Evas_Object *o = e_icon_add(popup->e);
|
||||||
|
|
||||||
|
e_icon_file_set(o, item);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static Popup_Data *
|
static Popup_Data *
|
||||||
_notification_popup_new(E_Notification_Notify *n, unsigned id)
|
_notification_popup_new(E_Notification_Notify *n, unsigned id)
|
||||||
{
|
{
|
||||||
|
@ -307,6 +378,7 @@ _notification_popup_new(E_Notification_Notify *n, unsigned id)
|
||||||
|
|
||||||
/* Setup the theme */
|
/* Setup the theme */
|
||||||
popup->theme = edje_object_add(popup->e);
|
popup->theme = edje_object_add(popup->e);
|
||||||
|
edje_object_item_provider_set(popup->theme, _cb_item_provider, popup);
|
||||||
e_theme_edje_object_set(popup->theme,
|
e_theme_edje_object_set(popup->theme,
|
||||||
"base/theme/modules/notification",
|
"base/theme/modules/notification",
|
||||||
"e/modules/notification/main");
|
"e/modules/notification/main");
|
||||||
|
@ -318,14 +390,17 @@ _notification_popup_new(E_Notification_Notify *n, unsigned id)
|
||||||
evas_object_event_callback_add(popup->win, EVAS_CALLBACK_DEL, _notification_popup_del_cb, popup);
|
evas_object_event_callback_add(popup->win, EVAS_CALLBACK_DEL, _notification_popup_del_cb, popup);
|
||||||
|
|
||||||
edje_object_signal_callback_add
|
edje_object_signal_callback_add
|
||||||
(popup->theme, "notification,deleted", "theme",
|
(popup->theme, "notification,deleted", "*",
|
||||||
(Edje_Signal_Cb)_notification_theme_cb_deleted, popup);
|
(Edje_Signal_Cb)_notification_theme_cb_deleted, popup);
|
||||||
edje_object_signal_callback_add
|
edje_object_signal_callback_add
|
||||||
(popup->theme, "notification,close", "theme",
|
(popup->theme, "notification,close", "*",
|
||||||
(Edje_Signal_Cb)_notification_theme_cb_close, popup);
|
(Edje_Signal_Cb)_notification_theme_cb_close, popup);
|
||||||
edje_object_signal_callback_add
|
edje_object_signal_callback_add
|
||||||
(popup->theme, "notification,find", "theme",
|
(popup->theme, "notification,find", "*",
|
||||||
(Edje_Signal_Cb)_notification_theme_cb_find, popup);
|
(Edje_Signal_Cb)_notification_theme_cb_find, popup);
|
||||||
|
edje_object_signal_callback_add
|
||||||
|
(popup->theme, "anchor,mouse,clicked,1,*", "notification.textblock.message",
|
||||||
|
(Edje_Signal_Cb)_notification_theme_cb_anchor, popup);
|
||||||
|
|
||||||
_notification_popup_refresh(popup);
|
_notification_popup_refresh(popup);
|
||||||
next_pos = _notification_popup_place(popup, next_pos);
|
next_pos = _notification_popup_place(popup, next_pos);
|
||||||
|
@ -386,17 +461,35 @@ _notification_popup_refresh(Popup_Data *popup)
|
||||||
const char *app_icon_max;
|
const char *app_icon_max;
|
||||||
int w, h, width = 80, height = 80;
|
int w, h, width = 80, height = 80;
|
||||||
E_Zone *zone;
|
E_Zone *zone;
|
||||||
|
Evas_Object *o;
|
||||||
|
|
||||||
if (!popup) return;
|
if (!popup) return;
|
||||||
|
|
||||||
popup->app_name = popup->notif->app_name;
|
popup->app_name = popup->notif->app_name;
|
||||||
|
|
||||||
|
EINA_LIST_FREE(popup->actions, o)
|
||||||
|
{
|
||||||
|
evas_object_del(o);
|
||||||
|
}
|
||||||
|
if (popup->action_box)
|
||||||
|
{
|
||||||
|
e_comp_object_util_del_list_remove(popup->win, popup->action_box);
|
||||||
|
E_FREE_FUNC(popup->action_box, evas_object_del);
|
||||||
|
edje_object_signal_emit(popup->theme, "e,state,actions,hide", "e");
|
||||||
|
}
|
||||||
|
|
||||||
if (popup->app_icon)
|
if (popup->app_icon)
|
||||||
{
|
{
|
||||||
e_comp_object_util_del_list_remove(popup->win, popup->app_icon);
|
e_comp_object_util_del_list_remove(popup->win, popup->app_icon);
|
||||||
E_FREE_FUNC(popup->app_icon, evas_object_del);
|
E_FREE_FUNC(popup->app_icon, evas_object_del);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (popup->desktop_icon)
|
||||||
|
{
|
||||||
|
e_comp_object_util_del_list_remove(popup->win, popup->desktop_icon);
|
||||||
|
E_FREE_FUNC(popup->desktop_icon, evas_object_del);
|
||||||
|
}
|
||||||
|
|
||||||
app_icon_max = edje_object_data_get(popup->theme, "app_icon_max");
|
app_icon_max = edje_object_data_get(popup->theme, "app_icon_max");
|
||||||
if (app_icon_max)
|
if (app_icon_max)
|
||||||
{
|
{
|
||||||
|
@ -452,7 +545,7 @@ _notification_popup_refresh(Popup_Data *popup)
|
||||||
icon_path = new_path;
|
icon_path = new_path;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Evas_Object *o = e_icon_add(popup->e);
|
o = e_icon_add(popup->e);
|
||||||
if (!e_util_icon_theme_set(o, icon_path))
|
if (!e_util_icon_theme_set(o, icon_path))
|
||||||
evas_object_del(o);
|
evas_object_del(o);
|
||||||
else
|
else
|
||||||
|
@ -510,12 +603,79 @@ _notification_popup_refresh(Popup_Data *popup)
|
||||||
popup->app_icon);
|
popup->app_icon);
|
||||||
edje_object_signal_emit(popup->theme, "notification,icon", "notification");
|
edje_object_signal_emit(popup->theme, "notification,icon", "notification");
|
||||||
|
|
||||||
|
if ((popup->notif->desktop_entry) &&
|
||||||
|
(edje_object_part_exists(popup->theme, "notification.swallow.desktop_icon")))
|
||||||
|
{
|
||||||
|
Efreet_Desktop *desktop;
|
||||||
|
unsigned int size;
|
||||||
|
const char *icon_path;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "%s.desktop", popup->notif->desktop_entry);
|
||||||
|
desktop = efreet_util_desktop_file_id_find(buf);
|
||||||
|
if ((desktop) && (desktop->icon))
|
||||||
|
{
|
||||||
|
size = e_util_icon_size_normalize(width * e_scale);
|
||||||
|
icon_path = efreet_icon_path_find(e_config->icon_theme,
|
||||||
|
desktop->icon, size);
|
||||||
|
efreet_desktop_free(desktop);
|
||||||
|
|
||||||
|
o = e_icon_add(popup->e);
|
||||||
|
if (!e_util_icon_theme_set(o, icon_path))
|
||||||
|
evas_object_del(o);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
popup->desktop_icon = o;
|
||||||
|
edje_object_part_swallow(popup->theme,
|
||||||
|
"notification.swallow.desktop_icon",
|
||||||
|
popup->desktop_icon);
|
||||||
|
evas_object_show(o);
|
||||||
|
e_comp_object_util_del_list_append(popup->win, o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Fill up the event message */
|
/* Fill up the event message */
|
||||||
_notification_format_message(popup);
|
_notification_format_message(popup);
|
||||||
|
|
||||||
|
if (popup->notif->actions)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
o = popup->action_box = elm_box_add(e_comp->elm);
|
||||||
|
elm_box_homogeneous_set(o, EINA_TRUE);
|
||||||
|
elm_box_horizontal_set(o, EINA_TRUE);
|
||||||
|
e_comp_object_util_del_list_append(popup->win, o);
|
||||||
|
for (i = 0; popup->notif->actions[i].action; i++)
|
||||||
|
{
|
||||||
|
o = edje_object_add(popup->e);
|
||||||
|
e_theme_edje_object_set(o,
|
||||||
|
"base/theme/modules/notification",
|
||||||
|
"e/modules/notification/action");
|
||||||
|
evas_object_data_set(o, "action", popup->notif->actions[i].action);
|
||||||
|
edje_object_part_text_unescaped_set(o, "e.text.label",
|
||||||
|
popup->notif->actions[i].label);
|
||||||
|
edje_object_signal_callback_add
|
||||||
|
(o, "e,action,clicked", "e",
|
||||||
|
(Edje_Signal_Cb)_notification_theme_cb_action, popup);
|
||||||
|
edje_object_size_min_calc(o, &w, &h);
|
||||||
|
evas_object_size_hint_min_set(o, w, h);
|
||||||
|
printf("NOT: act %ix%i\n", w, h);
|
||||||
|
elm_box_pack_end(popup->action_box, o);
|
||||||
|
evas_object_show(o);
|
||||||
|
}
|
||||||
|
// evas_smart_objects_calculate(popup->e);
|
||||||
|
// edje_message_signal_process();
|
||||||
|
evas_smart_objects_calculate(popup->e);
|
||||||
|
evas_object_size_hint_min_get(popup->action_box, &w, &h);
|
||||||
|
printf("NOT: actbox %ix%i\n", w, h);
|
||||||
|
edje_object_part_swallow(popup->theme, "notification.swallow.actions", popup->action_box);
|
||||||
|
edje_object_signal_emit(popup->theme, "e,state,actions,show", "e");
|
||||||
|
}
|
||||||
|
|
||||||
/* Compute the new size of the popup */
|
/* Compute the new size of the popup */
|
||||||
edje_object_calc_force(popup->theme);
|
edje_object_calc_force(popup->theme);
|
||||||
edje_object_size_min_calc(popup->theme, &w, &h);
|
edje_object_size_min_calc(popup->theme, &w, &h);
|
||||||
|
printf("NOT: min %ix%i\n", w, h);
|
||||||
if ((zone = e_comp_object_util_zone_get(popup->win)))
|
if ((zone = e_comp_object_util_zone_get(popup->win)))
|
||||||
{
|
{
|
||||||
w = MIN(w, zone->w / 2);
|
w = MIN(w, zone->w / 2);
|
||||||
|
@ -585,13 +745,18 @@ _notification_format_message(Popup_Data *popup)
|
||||||
{
|
{
|
||||||
Evas_Object *o = popup->theme;
|
Evas_Object *o = popup->theme;
|
||||||
Eina_Strbuf *buf = eina_strbuf_new();
|
Eina_Strbuf *buf = eina_strbuf_new();
|
||||||
|
|
||||||
|
printf("NOT: set message... [%s]\n", popup->notif->body);
|
||||||
edje_object_part_text_unescaped_set(o, "notification.text.title",
|
edje_object_part_text_unescaped_set(o, "notification.text.title",
|
||||||
popup->notif->summary);
|
popup->notif->summary);
|
||||||
/* FIXME: Filter to only include allowed markup? */
|
/* FIXME: Filter to only include allowed markup? */
|
||||||
/* We need to replace \n with <ps/>. FIXME: We need to handle all the
|
/* We need to replace \n with <ps/>. FIXME: We need to handle all the
|
||||||
* newline kinds, and paragraph separator. ATM this will suffice. */
|
* newline kinds, and paragraph separator. ATM this will suffice. */
|
||||||
eina_strbuf_append(buf, popup->notif->body);
|
eina_strbuf_append(buf, popup->notif->body);
|
||||||
eina_strbuf_replace_all(buf, "\n", "<br/>");
|
eina_strbuf_replace_all(buf, "\n", "<br/>");
|
||||||
|
// message is thge shadow sizer part
|
||||||
|
edje_object_part_text_set(o, "message",
|
||||||
|
eina_strbuf_string_get(buf));
|
||||||
edje_object_part_text_set(o, "notification.textblock.message",
|
edje_object_part_text_set(o, "notification.textblock.message",
|
||||||
eina_strbuf_string_get(buf));
|
eina_strbuf_string_get(buf));
|
||||||
eina_strbuf_free(buf);
|
eina_strbuf_free(buf);
|
||||||
|
|
Loading…
Reference in New Issue