Package: pidgin-libnotify
Version: 0.14-6
Severity: wishlist
Tags: l10n patch
--- Please enter the report below this line. ---
Pidgin uses simple dialog windows to request user action on some events like
voice call or
accepting an incoming file transfer. These dialogs
- might get easily obscured by other windows or simply get unnoticed on a
desktop with many open windows
and many virtual desktops
- may seem ugly to some people
Libnotify popups can be optionally used instead, because
- they are more noticeable on the screen and better attract user's attention to
important events
- their usage contributes to more consistent desktop environment and thus
improving user experience
This patch replaces Pidgin's action request dialogs, the ones displayed by
calling purple_request_action()
or purple_request_action_with_icon(), with libnotify popup bubbles. User then
interacts with the request
by pressing one of the buttons on the bubble. Correct function requires that
- user enabled the feature in pidgin-libnotify plugin configuration
- notification daemon implementing Desktop Notifications Specification DBUS
interface is running
- the daemon supports "actions" server capability and so is able to display
action buttons on the
notification bubble
If any of these conditions is not met, plugin's behavior reverts back to
displaying standard Pidgin
action request dialogs.
--- System information. ---
Architecture: amd64
Kernel: Linux 3.0.0-1-amd64
Debian Release: wheezy/sid
500 unstable ftp.cz.debian.org
500 unstable emdebian.org
500 testing www.debian-multimedia.org
500 testing security.debian.org
500 testing ftp.cz.debian.org
1 experimental ftp.debian.org
--- Package information. ---
Depends (Version) | Installed
==================================-+-============
libatk1.0-0 (>= 1.12.4) | 2.0.1-2
libc6 (>= 2.2.5) | 2.13-18
libcairo2 (>= 1.2.4) | 1.10.2-6.1
libfontconfig1 (>= 2.8.0) | 2.8.0-3
libfreetype6 (>= 2.2.1) | 2.4.6-2
libgdk-pixbuf2.0-0 (>= 2.22.0) | 2.23.5-3
libglib2.0-0 (>= 2.28.0) | 2.28.6-1
libgtk2.0-0 (>= 2.8.0) | 2.24.4-3
libnotify4 (>= 0.7.0) | 0.7.3-2
libpango1.0-0 (>= 1.14.0) | 1.28.4-3
pidgin (<< 3.0) | 2.10.0-1
pidgin (>= 2.10) | 2.10.0-1
Package's Recommends field is empty.
Package's Suggests field is empty.
>From 9c39dfc1c415d017057f8a87d503b9a3f9f26603 Mon Sep 17 00:00:00 2001
From: Jakub Adam <[email protected]>
Date: Tue, 6 Sep 2011 22:58:23 +0200
Subject: [PATCH] replace-pidgin-action-requests.diff
---
po/cs.po | 20 +++--
src/Makefile.am | 3 +
src/common.c | 67 ++++++++++++++++++
src/common.h | 38 ++++++++++
src/pidgin-libnotify.c | 37 +++++-----
src/request.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 320 insertions(+), 27 deletions(-)
create mode 100644 src/common.c
create mode 100644 src/common.h
create mode 100644 src/request.c
diff --git a/po/cs.po b/po/cs.po
index 4cb2ea7..c213260 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Project-Id-Version: pidgin-libnotify\n"
-"POT-Creation-Date: 2011-08-21 12:58+0200\n"
+"POT-Creation-Date: 2011-09-06 22:17+0200\n"
"PO-Revision-Date: 2011-08-21 00:00::00+GMT\n"
"Last-Translator: Jakub Adam <[email protected]>\n"
"MIME-Version: 1.0\n"
@@ -45,34 +45,38 @@ msgstr "Kamarád se odhlásil"
msgid "Only when available"
msgstr "Jen, když jsem k dispozici"
-#: ../src/pidgin-libnotify.c:342
+#: ../src/pidgin-libnotify.c:102
+msgid "Replace Pidgin request dialogs with libnotify popups"
+msgstr "Nahradit dotazovacà dialogy Pidginu"
+
+#: ../src/pidgin-libnotify.c:338
msgid "Show"
msgstr "Ukaž"
-#: ../src/pidgin-libnotify.c:375
+#: ../src/pidgin-libnotify.c:368
#, c-format
msgid "%s signed on"
msgstr "%s se pÅihlásil"
-#: ../src/pidgin-libnotify.c:407
+#: ../src/pidgin-libnotify.c:400
#, c-format
msgid "%s signed off"
msgstr "%s se odhlásil"
-#: ../src/pidgin-libnotify.c:434
+#: ../src/pidgin-libnotify.c:427
#, c-format
msgid "%s says:"
msgstr "%s napsal:"
-#: ../src/pidgin-libnotify.c:610
+#: ../src/pidgin-libnotify.c:606
msgid "Libnotify Popups"
msgstr "Vyskakovacà okna libnotify"
-#: ../src/pidgin-libnotify.c:611
+#: ../src/pidgin-libnotify.c:607
msgid "Displays popups via libnotify."
msgstr "Zobrazuje vyskakovacà okna pomocà libnotify"
-#: ../src/pidgin-libnotify.c:612
+#: ../src/pidgin-libnotify.c:608
msgid ""
"Pidgin-libnotify:\n"
"Displays popups via libnotify."
diff --git a/src/Makefile.am b/src/Makefile.am
index ea0d757..ca00c87 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,6 +8,9 @@ gd_LTLIBRARIES = pidgin-libnotify.la
pidgin_libnotify_la_SOURCES = \
pidgin-libnotify.c \
+ common.h \
+ common.c \
+ request.c \
gln_intl.h
pidgin_libnotify_la_LIBADD = $(LIBNOTIFY_LIBS) $(DBUS_LIBS) $(GTK_LIBS)
diff --git a/src/common.c b/src/common.c
new file mode 100644
index 0000000..1b22dc0
--- /dev/null
+++ b/src/common.c
@@ -0,0 +1,67 @@
+/*
+ * Pidgin-libnotify - Provides a libnotify interface for Pidgin
+ * Copyright (C) 2005-2007 Duarte Henriques
+ * Copyright (C) 2011 Jakub Adam
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "common.h"
+
+#include <debug.h>
+#include <request.h>
+
+gboolean
+server_has_caps(const char *id)
+{
+ GList *caps = notify_get_server_caps();
+ gboolean result;
+ result = (g_list_find_custom(caps, id, (GCompareFunc)g_strcmp0) != NULL);
+ g_list_free_full(caps, g_free);
+ return result;
+}
+
+typedef struct {
+ int id;
+ PurpleRequestActionCb callback;
+} ActionData;
+
+NotifyNotification *
+notification_new(const gchar *title, const gchar *body)
+{
+ NotifyNotification *notification;
+
+/* libnotify 0.7.0 and later has no support for attaching to widgets */
+#if NOTIFY_CHECK_VERSION(0,7,0)
+ notification = notify_notification_new(title, body, NULL);
+#else
+ notification = notify_notification_new(title, body, NULL, NULL);
+#endif
+ purple_debug_info(PLUGIN_ID, "notification_new(), title: '%s', body: '%s'",
+ title, body);
+
+ notify_notification_set_urgency(notification, NOTIFY_URGENCY_NORMAL);
+
+ return notification;
+}
+
+void
+notification_show(NotifyNotification *notification)
+{
+ if (!notify_notification_show (notification, NULL)) {
+ purple_debug_error (PLUGIN_ID, "notification_show(), "
+ "failed to send notification\n");
+ }
+}
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..e6cdd92
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,38 @@
+/*
+ * Pidgin-libnotify - Provides a libnotify interface for Pidgin
+ * Copyright (C) 2005-2007 Duarte Henriques
+ * Copyright (C) 2011 Jakub Adam
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PIDGIN_LIBNOTIFY_COMMON_H
+#define PIDGIN_LIBNOTIFY_COMMON_H
+
+#include <libnotify/notify.h>
+
+#define PLUGIN_ID "pidgin-libnotify"
+
+#ifndef NOTIFY_CHECK_VERSION
+#define NOTIFY_CHECK_VERSION(x,y,z) 0
+#endif
+
+gboolean server_has_caps(const char *id);
+
+NotifyNotification * notification_new(const gchar *title, const gchar *body);
+
+void notification_show(NotifyNotification *notification);
+
+#endif // PIDGIN_LIBNOTIFY_COMMON_H
diff --git a/src/pidgin-libnotify.c b/src/pidgin-libnotify.c
index 3317610..161f8f9 100644
--- a/src/pidgin-libnotify.c
+++ b/src/pidgin-libnotify.c
@@ -21,6 +21,7 @@
#include <config.h>
#endif
+#include "common.h"
#include "gln_intl.h"
#ifndef PURPLE_PLUGINS
@@ -96,6 +97,11 @@ get_plugin_pref_frame (PurplePlugin *plugin)
_("Only when available"));
purple_plugin_pref_frame_add (frame, ppref);
+ ppref = purple_plugin_pref_new_with_name_and_label (
+ "/plugins/gtk/libnotify/replace_requests",
+ _("Replace Pidgin request dialogs with libnotify popups"));
+ purple_plugin_pref_frame_add (frame, ppref);
+
return frame;
}
@@ -278,7 +284,6 @@ notify (const gchar *title,
PurpleBuddyIcon *buddy_icon;
gchar *tr_body;
PurpleContact *contact;
- GList *caps;
contact = purple_buddy_get_contact (buddy);
@@ -301,15 +306,8 @@ notify (const gchar *title,
g_free (tr_body);
return;
}
-/* libnotify 0.7.0 and later has no support for attaching to widgets */
-#if NOTIFY_CHECK_VERSION(0,7,0)
- notification = notify_notification_new (title, tr_body, NULL);
-#else
- notification = notify_notification_new (title, tr_body, NULL, NULL);
-#endif
- purple_debug_info (PLUGIN_ID, "notify(), new: "
- "title: '%s', body: '%s', buddy: '%s'\n",
- title, tr_body, best_name (buddy));
+
+ notification = notification_new (title, tr_body);
g_free (tr_body);
@@ -336,18 +334,11 @@ notify (const gchar *title,
g_signal_connect (notification, "closed", G_CALLBACK(closed_cb), NULL);
- notify_notification_set_urgency (notification, NOTIFY_URGENCY_NORMAL);
-
- caps = notify_get_server_caps ();
- if (g_list_find_custom (caps, "actions", (GCompareFunc)g_strcmp0)) {
+ if (server_has_caps ("actions")) {
notify_notification_add_action (notification, "show", _("Show"), action_cb, NULL, NULL);
}
- g_list_free_full (caps, g_free);
-
- if (!notify_notification_show (notification, NULL)) {
- purple_debug_error (PLUGIN_ID, "notify(), failed to send notification\n");
- }
+ notification_show (notification);
}
static void
@@ -500,6 +491,9 @@ notify_new_chat_cb (PurpleAccount *account,
notify_msg_sent (account, sender, message);
}
+extern void attach_request_ui_ops ();
+extern void detach_request_ui_ops ();
+
static gboolean
plugin_load (PurplePlugin *plugin)
{
@@ -532,6 +526,8 @@ plugin_load (PurplePlugin *plugin)
purple_signal_connect (conn_handle, "signed-on", plugin,
PURPLE_CALLBACK(event_connection_throttle), NULL);
+ attach_request_ui_ops ();
+
return TRUE;
}
@@ -559,6 +555,8 @@ plugin_unload (PurplePlugin *plugin)
purple_signal_disconnect (conn_handle, "signed-on", plugin,
PURPLE_CALLBACK(event_connection_throttle));
+ detach_request_ui_ops ();
+
g_hash_table_destroy (buddy_hash);
notify_uninit ();
@@ -618,6 +616,7 @@ init_plugin (PurplePlugin *plugin)
purple_prefs_add_bool ("/plugins/gtk/libnotify/signon", TRUE);
purple_prefs_add_bool ("/plugins/gtk/libnotify/signoff", FALSE);
purple_prefs_add_bool ("/plugins/gtk/libnotify/only_available", FALSE);
+ purple_prefs_add_bool ("/plugins/gtk/libnotify/replace_requests", FALSE);
}
PURPLE_INIT_PLUGIN(notify, init_plugin, info)
diff --git a/src/request.c b/src/request.c
new file mode 100644
index 0000000..0957c31
--- /dev/null
+++ b/src/request.c
@@ -0,0 +1,182 @@
+/*
+ * Pidgin-libnotify - Provides a libnotify interface for Pidgin
+ * Copyright (C) 2011 Jakub Adam
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <debug.h>
+#include <gtkutils.h>
+#include <request.h>
+
+#include <string.h>
+
+#include "common.h"
+
+typedef struct {
+ int id;
+ PurpleRequestActionCb callback;
+} ActionData;
+
+static void
+action_cb (NotifyNotification *notification, char *action,
+ ActionData *data)
+{
+ data->callback(g_object_get_data(G_OBJECT(notification), "user_data"),
+ data->id);
+}
+
+GSList *req_notifications = NULL;
+
+static gboolean
+closed_cb (NotifyNotification *notification)
+{
+ req_notifications = g_slist_remove(req_notifications, notification);
+ g_object_unref(G_OBJECT(notification));
+
+ return FALSE;
+}
+
+static gchar *
+remove_accelerators (const gchar *s)
+{
+ gchar **split = g_strsplit(s, "_", -1);
+ gchar *result = g_strjoinv("", split);
+ g_strfreev(split);
+ return result;
+}
+
+static PurpleRequestUiOps ops;
+static PurpleRequestUiOps *original_ops = NULL;
+
+static void *
+notify_request_action_with_icon(const char *title, const char *primary,
+ const char *secondary, int default_action,
+ PurpleAccount *account, const char *who,
+ PurpleConversation *conv,
+ gconstpointer icon_data, gsize icon_size,
+ void *user_data,
+ size_t action_count, va_list actions)
+{
+ NotifyNotification *notification;
+ int i;
+
+ if (!purple_prefs_get_bool("/plugins/gtk/libnotify/replace_requests") ||
+ !server_has_caps("actions")) {
+ return original_ops->request_action_with_icon(title, primary, secondary,
+ default_action, account,
+ who, conv, icon_data,
+ icon_size, user_data,
+ action_count, actions);
+ }
+
+ notification = notification_new(primary, secondary);
+
+ if (icon_data) {
+ GdkPixbuf *pixbuf = pidgin_pixbuf_from_data(icon_data, icon_size);
+ if (pixbuf) {
+ notify_notification_set_icon_from_pixbuf(notification, pixbuf);
+ g_object_unref (pixbuf);
+ } else {
+ purple_debug_warning(PLUGIN_ID, "notify_request_action_with_icon(), "
+ "failed to parse request icon\n");
+ }
+ }
+
+ notify_notification_set_hint(notification, "resident",
+ g_variant_new_boolean(TRUE));
+ notify_notification_set_timeout(notification, NOTIFY_EXPIRES_NEVER);
+
+ g_signal_connect(notification, "closed", G_CALLBACK(closed_cb), NULL);
+
+ for (i = 0; i != action_count; ++i) {
+ char *label = remove_accelerators(va_arg (actions, const char *));
+ ActionData *data = g_new(ActionData, 1);
+ data->id = i;
+ data->callback = va_arg(actions, PurpleRequestActionCb);
+
+ notify_notification_add_action(notification,
+ (default_action == i) ? "default" : label,
+ label,
+ (NotifyActionCallback) action_cb,
+ data, g_free);
+ g_free(label);
+ }
+
+ g_object_set_data(G_OBJECT(notification), "user_data", user_data);
+
+ req_notifications = g_slist_append(req_notifications, notification);
+
+ notification_show(notification);
+
+ return notification;
+}
+
+static void *
+notify_request_action(const char *title, const char *primary,
+ const char *secondary, int default_action,
+ PurpleAccount *account, const char *who,
+ PurpleConversation *conv, void *user_data,
+ size_t action_count, va_list actions)
+{
+ if (!purple_prefs_get_bool("/plugins/gtk/libnotify/replace_requests") ||
+ !server_has_caps("actions")) {
+ return original_ops->request_action(title, primary, secondary,
+ default_action, account, who, conv,
+ user_data, action_count, actions);
+ }
+
+ return notify_request_action_with_icon(title, primary, secondary,
+ default_action, account, who, conv,
+ NULL, 0, user_data, action_count,
+ actions);
+}
+
+static void
+notify_close_request(PurpleRequestType type, void *ui_handle)
+{
+ GSList *l = g_slist_find(req_notifications, ui_handle);
+ if (l) {
+ NotifyNotification *notification = l->data;
+ notify_notification_close(notification, NULL);
+ } else {
+ original_ops->close_request(type, ui_handle);
+ }
+}
+
+void
+attach_request_ui_ops()
+{
+ original_ops = purple_request_get_ui_ops();
+ if (original_ops) {
+ memcpy(&ops, original_ops, sizeof (ops));
+ ops.request_action = notify_request_action;
+ ops.request_action_with_icon = notify_request_action_with_icon;
+ ops.close_request = notify_close_request;
+ purple_request_set_ui_ops(&ops);
+ }
+}
+
+void
+detach_request_ui_ops()
+{
+ if (original_ops) {
+ purple_request_set_ui_ops(original_ops);
+ }
+}
--
1.7.5.4