1
0
mirror of https://gitlab.gnome.org/GNOME/glib.git synced 2025-10-08 22:50:06 +02:00
Files
.gitlab-ci
docs
fuzzing
gio
completion
fam
gdbus-2.0
gvdb
inotify
kqueue
tests
win32
xdgmime
data-to-c.py
dbus-daemon.xml
gaction.c
gaction.h
gactiongroup.c
gactiongroup.h
gactiongroupexporter.c
gactiongroupexporter.h
gactionmap.c
gactionmap.h
gappinfo.c
gappinfo.h
gappinfoprivate.h
gapplication-tool.c
gapplication.c
gapplication.h
gapplicationcommandline.c
gapplicationcommandline.h
gapplicationimpl-dbus.c
gapplicationimpl.h
gasynchelper.c
gasynchelper.h
gasyncinitable.c
gasyncinitable.h
gasyncresult.c
gasyncresult.h
gbufferedinputstream.c
gbufferedinputstream.h
gbufferedoutputstream.c
gbufferedoutputstream.h
gbytesicon.c
gbytesicon.h
gcancellable.c
gcancellable.h
gcharsetconverter.c
gcharsetconverter.h
gcocoanotificationbackend.m
gcontenttype-win32.c
gcontenttype.c
gcontenttype.h
gcontenttypeprivate.h
gcontextspecificgroup.c
gcontextspecificgroup.h
gconverter.c
gconverter.h
gconverterinputstream.c
gconverterinputstream.h
gconverteroutputstream.c
gconverteroutputstream.h
gcredentials.c
gcredentials.h
gcredentialsprivate.h
gdatagrambased.c
gdatagrambased.h
gdatainputstream.c
gdatainputstream.h
gdataoutputstream.c
gdataoutputstream.h
gdbus-tool.c
gdbusactiongroup-private.h
gdbusactiongroup.c
gdbusactiongroup.h
gdbusaddress.c
gdbusaddress.h
gdbusauth.c
gdbusauth.h
gdbusauthmechanism.c
gdbusauthmechanism.h
gdbusauthmechanismanon.c
gdbusauthmechanismanon.h
gdbusauthmechanismexternal.c
gdbusauthmechanismexternal.h
gdbusauthmechanismsha1.c
gdbusauthmechanismsha1.h
gdbusauthobserver.c
gdbusauthobserver.h
gdbusconnection.c
gdbusconnection.h
gdbusdaemon.c
gdbusdaemon.h
gdbuserror.c
gdbuserror.h
gdbusinterface.c
gdbusinterface.h
gdbusinterfaceskeleton.c
gdbusinterfaceskeleton.h
gdbusintrospection.c
gdbusintrospection.h
gdbusmenumodel.c
gdbusmenumodel.h
gdbusmessage.c
gdbusmessage.h
gdbusmethodinvocation.c
gdbusmethodinvocation.h
gdbusnameowning.c
gdbusnameowning.h
gdbusnamewatching.c
gdbusnamewatching.h
gdbusobject.c
gdbusobject.h
gdbusobjectmanager.c
gdbusobjectmanager.h
gdbusobjectmanagerclient.c
gdbusobjectmanagerclient.h
gdbusobjectmanagerserver.c
gdbusobjectmanagerserver.h
gdbusobjectproxy.c
gdbusobjectproxy.h
gdbusobjectskeleton.c
gdbusobjectskeleton.h
gdbusprivate.c
gdbusprivate.h
gdbusproxy.c
gdbusproxy.h
gdbusserver.c
gdbusserver.h
gdbusutils.c
gdbusutils.h
gdelayedsettingsbackend.c
gdelayedsettingsbackend.h
gdesktopappinfo.c
gdesktopappinfo.h
gdocumentportal.c
gdocumentportal.h
gdrive.c
gdrive.h
gdtlsclientconnection.c
gdtlsclientconnection.h
gdtlsconnection.c
gdtlsconnection.h
gdtlsserverconnection.c
gdtlsserverconnection.h
gdummyfile.c
gdummyfile.h
gdummyproxyresolver.c
gdummyproxyresolver.h
gdummytlsbackend.c
gdummytlsbackend.h
gemblem.c
gemblem.h
gemblemedicon.c
gemblemedicon.h
gfdonotificationbackend.c
gfile.c
gfile.h
gfileattribute-priv.h
gfileattribute.c
gfileattribute.h
gfiledescriptorbased.c
gfiledescriptorbased.h
gfileenumerator.c
gfileenumerator.h
gfileicon.c
gfileicon.h
gfileinfo-priv.h
gfileinfo.c
gfileinfo.h
gfileinputstream.c
gfileinputstream.h
gfileiostream.c
gfileiostream.h
gfilemonitor.c
gfilemonitor.h
gfilenamecompleter.c
gfilenamecompleter.h
gfileoutputstream.c
gfileoutputstream.h
gfilterinputstream.c
gfilterinputstream.h
gfilteroutputstream.c
gfilteroutputstream.h
ggtknotificationbackend.c
ghttpproxy.c
ghttpproxy.h
gicon.c
gicon.h
ginetaddress.c
ginetaddress.h
ginetaddressmask.c
ginetaddressmask.h
ginetsocketaddress.c
ginetsocketaddress.h
ginitable.c
ginitable.h
ginputstream.c
ginputstream.h
gio-autocleanups.h
gio-querymodules-wrapper.py
gio-querymodules.c
gio-tool-cat.c
gio-tool-copy.c
gio-tool-info.c
gio-tool-list.c
gio-tool-mime.c
gio-tool-mkdir.c
gio-tool-monitor.c
gio-tool-mount.c
gio-tool-move.c
gio-tool-open.c
gio-tool-remove.c
gio-tool-rename.c
gio-tool-save.c
gio-tool-set.c
gio-tool-trash.c
gio-tool-tree.c
gio-tool.c
gio-tool.h
gio.h
gio.rc.in
gio.stp.in
gio_probes.d
gio_trace.h
gioenums.h
gioenumtypes.c.template
gioenumtypes.h.template
gioerror.c
gioerror.h
giomodule-priv.c
giomodule-priv.h
giomodule.c
giomodule.h
gioprivate.h
gioscheduler.c
gioscheduler.h
giostream.c
giostream.h
giotypes.h
giowin32-priv.h
giowin32-private.c
gkeyfilesettingsbackend.c
glib-compile-resources.c
glib-compile-schemas.c
glistmodel.c
glistmodel.h
gliststore.c
gliststore.h
gloadableicon.c
gloadableicon.h
glocalfile.c
glocalfile.h
glocalfileenumerator.c
glocalfileenumerator.h
glocalfileinfo.c
glocalfileinfo.h
glocalfileinputstream.c
glocalfileinputstream.h
glocalfileiostream.c
glocalfileiostream.h
glocalfilemonitor.c
glocalfilemonitor.h
glocalfileoutputstream.c
glocalfileoutputstream.h
glocalvfs.c
glocalvfs.h
gmarshal-internal.c
gmarshal-internal.h
gmarshal-internal.list
gmemoryinputstream.c
gmemoryinputstream.h
gmemorymonitor.c
gmemorymonitor.h
gmemorymonitordbus.c
gmemorymonitordbus.h
gmemorymonitorportal.c
gmemorymonitorportal.h
gmemoryoutputstream.c
gmemoryoutputstream.h
gmemorysettingsbackend.c
gmenu.c
gmenu.h
gmenuexporter.c
gmenuexporter.h
gmenumodel.c
gmenumodel.h
gmount.c
gmount.h
gmountoperation.c
gmountoperation.h
gmountprivate.h
gnativesocketaddress.c
gnativesocketaddress.h
gnativevolumemonitor.c
gnativevolumemonitor.h
gnetworkaddress.c
gnetworkaddress.h
gnetworking.c
gnetworking.h.in
gnetworkingprivate.h
gnetworkmonitor.c
gnetworkmonitor.h
gnetworkmonitorbase.c
gnetworkmonitorbase.h
gnetworkmonitornetlink.c
gnetworkmonitornetlink.h
gnetworkmonitornm.c
gnetworkmonitornm.h
gnetworkmonitorportal.c
gnetworkmonitorportal.h
gnetworkservice.c
gnetworkservice.h
gnextstepsettingsbackend.m
gnotification-private.h
gnotification.c
gnotification.h
gnotificationbackend.c
gnotificationbackend.h
gnullsettingsbackend.c
gopenuriportal.c
gopenuriportal.h
gosxappinfo.h
gosxappinfo.m
gosxcontenttype.m
goutputstream.c
goutputstream.h
gpermission.c
gpermission.h
gpollableinputstream.c
gpollableinputstream.h
gpollableoutputstream.c
gpollableoutputstream.h
gpollableutils.c
gpollableutils.h
gpollfilemonitor.c
gpollfilemonitor.h
gportalnotificationbackend.c
gportalsupport.c
gportalsupport.h
gpropertyaction.c
gpropertyaction.h
gproxy.c
gproxy.h
gproxyaddress.c
gproxyaddress.h
gproxyaddressenumerator.c
gproxyaddressenumerator.h
gproxyresolver.c
gproxyresolver.h
gproxyresolverportal.c
gproxyresolverportal.h
gregistrysettingsbackend.c
gregistrysettingsbackend.h
gremoteactiongroup.c
gremoteactiongroup.h
gresolver.c
gresolver.h
gresource-tool.c
gresource.c
gresource.h
gresourcefile.c
gresourcefile.h
gschema.dtd
gschema.its
gschema.loc
gseekable.c
gseekable.h
gsettings-mapping.c
gsettings-mapping.h
gsettings-tool.c
gsettings.c
gsettings.h
gsettingsbackend.c
gsettingsbackend.h
gsettingsbackendinternal.h
gsettingsschema-internal.h
gsettingsschema.c
gsettingsschema.h
gsimpleaction.c
gsimpleaction.h
gsimpleactiongroup.c
gsimpleactiongroup.h
gsimpleasyncresult.c
gsimpleasyncresult.h
gsimpleiostream.c
gsimpleiostream.h
gsimplepermission.c
gsimplepermission.h
gsimpleproxyresolver.c
gsimpleproxyresolver.h
gsocket.c
gsocket.h
gsocketaddress.c
gsocketaddress.h
gsocketaddressenumerator.c
gsocketaddressenumerator.h
gsocketclient.c
gsocketclient.h
gsocketconnectable.c
gsocketconnectable.h
gsocketconnection.c
gsocketconnection.h
gsocketcontrolmessage.c
gsocketcontrolmessage.h
gsocketinputstream.c
gsocketinputstream.h
gsocketlistener.c
gsocketlistener.h
gsocketoutputstream.c
gsocketoutputstream.h
gsocketservice.c
gsocketservice.h
gsocks4aproxy.c
gsocks4aproxy.h
gsocks4proxy.c
gsocks4proxy.h
gsocks5proxy.c
gsocks5proxy.h
gsrvtarget.c
gsrvtarget.h
gsubprocess.c
gsubprocess.h
gsubprocesslauncher-private.h
gsubprocesslauncher.c
gsubprocesslauncher.h
gtask.c
gtask.h
gtcpconnection.c
gtcpconnection.h
gtcpwrapperconnection.c
gtcpwrapperconnection.h
gtestdbus.c
gtestdbus.h
gthemedicon.c
gthemedicon.h
gthreadedresolver.c
gthreadedresolver.h
gthreadedsocketservice.c
gthreadedsocketservice.h
gtlsbackend.c
gtlsbackend.h
gtlscertificate.c
gtlscertificate.h
gtlsclientconnection.c
gtlsclientconnection.h
gtlsconnection.c
gtlsconnection.h
gtlsdatabase.c
gtlsdatabase.h
gtlsfiledatabase.c
gtlsfiledatabase.h
gtlsinteraction.c
gtlsinteraction.h
gtlspassword.c
gtlspassword.h
gtlsserverconnection.c
gtlsserverconnection.h
gtrashportal.c
gtrashportal.h
gunionvolumemonitor.c
gunionvolumemonitor.h
gunixconnection.c
gunixconnection.h
gunixcredentialsmessage.c
gunixcredentialsmessage.h
gunixfdlist.c
gunixfdlist.h
gunixfdmessage.c
gunixfdmessage.h
gunixinputstream.c
gunixinputstream.h
gunixmount.c
gunixmount.h
gunixmounts.c
gunixmounts.h
gunixoutputstream.c
gunixoutputstream.h
gunixsocketaddress.c
gunixsocketaddress.h
gunixvolume.c
gunixvolume.h
gunixvolumemonitor.c
gunixvolumemonitor.h
gvfs.c
gvfs.h
gvolume.c
gvolume.h
gvolumemonitor.c
gvolumemonitor.h
gwin32appinfo.c
gwin32appinfo.h
gwin32inputstream.c
gwin32inputstream.h
gwin32mount.c
gwin32mount.h
gwin32networking.h
gwin32networkmonitor.c
gwin32networkmonitor.h
gwin32notificationbackend.c
gwin32outputstream.c
gwin32outputstream.h
gwin32registrykey.c
gwin32registrykey.h
gwin32volumemonitor.c
gwin32volumemonitor.h
gzlibcompressor.c
gzlibcompressor.h
gzlibdecompressor.c
gzlibdecompressor.h
meson.build
org.freedesktop.portal.Documents.xml
org.freedesktop.portal.OpenURI.xml
org.freedesktop.portal.ProxyResolver.xml
org.freedesktop.portal.Trash.xml
strinfo.c
thumbnail-verify.c
thumbnail-verify.h
glib
gmodule
gobject
gthread
m4macros
po
subprojects
tests
.clang-format
.dir-locals.el
.gitattributes
.gitignore
.gitlab-ci.yml
AUTHORS
CONTRIBUTING.md
COPYING
HACKING
INSTALL.in
NEWS
NEWS.pre-1-3
README
README.md
README.rationale
README.win32
README.win32.md
check-abis.sh
clang-format-diff.py
glib-gettextize.in
glib.doap
glib.supp
meson.build
meson_options.txt
msvc_recommended_pragmas.h
sanity_check
template-tap.test.in
template.test.in
glib/gio/gfdonotificationbackend.c

506 lines
16 KiB
C
Raw Normal View History

/*
* Copyright © 2013 Lars Uebernickel
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
2014-01-23 12:58:29 +01:00
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Authors: Lars Uebernickel <lars@uebernic.de>
*/
#include "config.h"
#include "gnotificationbackend.h"
#include "gapplication.h"
#include "giomodule-priv.h"
#include "gnotification-private.h"
#include "gdbusconnection.h"
#include "gdbusnamewatching.h"
#include "gactiongroup.h"
#include "gaction.h"
#include "gthemedicon.h"
#include "gfileicon.h"
#include "gfile.h"
#include "gdbusutils.h"
#define G_TYPE_FDO_NOTIFICATION_BACKEND (g_fdo_notification_backend_get_type ())
#define G_FDO_NOTIFICATION_BACKEND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_FDO_NOTIFICATION_BACKEND, GFdoNotificationBackend))
typedef struct _GFdoNotificationBackend GFdoNotificationBackend;
typedef GNotificationBackendClass GFdoNotificationBackendClass;
struct _GFdoNotificationBackend
{
GNotificationBackend parent;
guint bus_name_id;
guint notify_subscription;
GSList *notifications;
};
GType g_fdo_notification_backend_get_type (void);
G_DEFINE_TYPE_WITH_CODE (GFdoNotificationBackend, g_fdo_notification_backend, G_TYPE_NOTIFICATION_BACKEND,
_g_io_modules_ensure_extension_points_registered ();
g_io_extension_point_implement (G_NOTIFICATION_BACKEND_EXTENSION_POINT_NAME,
g_define_type_id, "freedesktop", 0))
typedef struct
{
GFdoNotificationBackend *backend;
gchar *id;
guint32 notify_id;
gchar *default_action;
GVariant *default_action_target;
} FreedesktopNotification;
static void
freedesktop_notification_free (gpointer data)
{
FreedesktopNotification *n = data;
g_object_unref (n->backend);
g_free (n->id);
g_free (n->default_action);
if (n->default_action_target)
g_variant_unref (n->default_action_target);
g_slice_free (FreedesktopNotification, n);
}
static FreedesktopNotification *
freedesktop_notification_new (GFdoNotificationBackend *backend,
const gchar *id,
GNotification *notification)
{
FreedesktopNotification *n;
n = g_slice_new0 (FreedesktopNotification);
n->backend = g_object_ref (backend);
n->id = g_strdup (id);
n->notify_id = 0;
g_notification_get_default_action (notification,
&n->default_action,
&n->default_action_target);
return n;
}
static FreedesktopNotification *
g_fdo_notification_backend_find_notification (GFdoNotificationBackend *backend,
const gchar *id)
{
GSList *it;
for (it = backend->notifications; it != NULL; it = it->next)
{
FreedesktopNotification *n = it->data;
if (g_str_equal (n->id, id))
return n;
}
return NULL;
}
static FreedesktopNotification *
g_fdo_notification_backend_find_notification_by_notify_id (GFdoNotificationBackend *backend,
guint32 id)
{
GSList *it;
for (it = backend->notifications; it != NULL; it = it->next)
{
FreedesktopNotification *n = it->data;
if (n->notify_id == id)
return n;
}
return NULL;
}
static void
activate_action (GFdoNotificationBackend *backend,
const gchar *name,
GVariant *parameter)
{
GNotificationBackend *g_backend = G_NOTIFICATION_BACKEND (backend);
if (name)
{
if (g_str_has_prefix (name, "app."))
g_action_group_activate_action (G_ACTION_GROUP (g_backend->application), name + 4, parameter);
}
else
{
g_application_activate (g_backend->application);
}
}
static void
notify_signal (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
GFdoNotificationBackend *backend = user_data;
guint32 id = 0;
const gchar *action = NULL;
FreedesktopNotification *n;
if (g_str_equal (signal_name, "NotificationClosed") &&
g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(uu)")))
{
g_variant_get (parameters, "(uu)", &id, NULL);
}
else if (g_str_equal (signal_name, "ActionInvoked") &&
g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(us)")))
{
g_variant_get (parameters, "(u&s)", &id, &action);
}
else
return;
n = g_fdo_notification_backend_find_notification_by_notify_id (backend, id);
if (n == NULL)
return;
if (action)
{
if (g_str_equal (action, "default"))
{
activate_action (backend, n->default_action, n->default_action_target);
}
else
{
gchar *name;
GVariant *target;
if (g_action_parse_detailed_name (action, &name, &target, NULL))
{
activate_action (backend, name, target);
g_free (name);
if (target)
g_variant_unref (target);
}
}
}
/* Get the notification again in case the action redrew it */
n = g_fdo_notification_backend_find_notification_by_notify_id (backend, id);
if (n != NULL)
{
backend->notifications = g_slist_remove (backend->notifications, n);
freedesktop_notification_free (n);
}
}
static void
name_vanished_handler_cb (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
GFdoNotificationBackend *backend = user_data;
if (backend->notifications)
{
g_slist_free_full (backend->notifications, freedesktop_notification_free);
backend->notifications = NULL;
}
}
/* Converts a GNotificationPriority to an urgency level as defined by
* the freedesktop spec (0: low, 1: normal, 2: critical).
*/
static guchar
urgency_from_priority (GNotificationPriority priority)
{
switch (priority)
{
case G_NOTIFICATION_PRIORITY_LOW:
return 0;
default:
case G_NOTIFICATION_PRIORITY_NORMAL:
case G_NOTIFICATION_PRIORITY_HIGH:
return 1;
case G_NOTIFICATION_PRIORITY_URGENT:
return 2;
}
}
static void
call_notify (GDBusConnection *con,
GApplication *app,
guint32 replace_id,
GNotification *notification,
GAsyncReadyCallback callback,
gpointer user_data)
{
GVariantBuilder action_builder;
guint n_buttons;
guint i;
GVariantBuilder hints_builder;
GIcon *icon;
GVariant *parameters;
const gchar *body;
guchar urgency;
g_variant_builder_init (&action_builder, G_VARIANT_TYPE_STRING_ARRAY);
if (g_notification_get_default_action (notification, NULL, NULL))
{
g_variant_builder_add (&action_builder, "s", "default");
g_variant_builder_add (&action_builder, "s", "");
}
n_buttons = g_notification_get_n_buttons (notification);
for (i = 0; i < n_buttons; i++)
{
gchar *label;
gchar *action;
GVariant *target;
gchar *detailed_name;
g_notification_get_button (notification, i, &label, &action, &target);
detailed_name = g_action_print_detailed_name (action, target);
/* Actions named 'default' collide with libnotify's naming of the
* default action. Rewriting them to something unique is enough,
* because those actions can never be activated (they aren't
* prefixed with 'app.').
*/
if (g_str_equal (detailed_name, "default"))
{
g_free (detailed_name);
detailed_name = g_dbus_generate_guid ();
}
g_variant_builder_add_value (&action_builder, g_variant_new_take_string (detailed_name));
g_variant_builder_add_value (&action_builder, g_variant_new_take_string (label));
g_free (action);
if (target)
g_variant_unref (target);
}
g_variant_builder_init (&hints_builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&hints_builder, "{sv}", "desktop-entry",
g_variant_new_string (g_application_get_application_id (app)));
urgency = urgency_from_priority (g_notification_get_priority (notification));
g_variant_builder_add (&hints_builder, "{sv}", "urgency", g_variant_new_byte (urgency));
icon = g_notification_get_icon (notification);
if (icon != NULL)
{
if (G_IS_FILE_ICON (icon))
{
GFile *file;
file = g_file_icon_get_file (G_FILE_ICON (icon));
g_variant_builder_add (&hints_builder, "{sv}", "image-path",
g_variant_new_take_string (g_file_get_path (file)));
}
else if (G_IS_THEMED_ICON (icon))
{
const gchar* const* icon_names = g_themed_icon_get_names(G_THEMED_ICON (icon));
/* Take first name from GThemedIcon */
g_variant_builder_add (&hints_builder, "{sv}", "image-path",
g_variant_new_string (icon_names[0]));
}
}
body = g_notification_get_body (notification);
parameters = g_variant_new ("(susssasa{sv}i)",
"", /* app name */
replace_id,
"", /* app icon */
g_notification_get_title (notification),
body ? body : "",
&action_builder,
&hints_builder,
-1); /* expire_timeout */
g_dbus_connection_call (con, "org.freedesktop.Notifications", "/org/freedesktop/Notifications",
"org.freedesktop.Notifications", "Notify",
parameters, G_VARIANT_TYPE ("(u)"),
G_DBUS_CALL_FLAGS_NONE, -1, NULL,
callback, user_data);
}
static void
notification_sent (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
FreedesktopNotification *n = user_data;
GVariant *val;
GError *error = NULL;
static gboolean warning_printed = FALSE;
val = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), result, &error);
if (val)
{
GFdoNotificationBackend *backend = n->backend;
FreedesktopNotification *match;
g_variant_get (val, "(u)", &n->notify_id);
g_variant_unref (val);
match = g_fdo_notification_backend_find_notification_by_notify_id (backend, n->notify_id);
if (match != NULL)
{
backend->notifications = g_slist_remove (backend->notifications, match);
freedesktop_notification_free (match);
}
backend->notifications = g_slist_prepend (backend->notifications, n);
}
else
{
if (!warning_printed)
{
g_warning ("unable to send notifications through org.freedesktop.Notifications: %s",
error->message);
warning_printed = TRUE;
}
freedesktop_notification_free (n);
g_error_free (error);
}
}
static void
g_fdo_notification_backend_dispose (GObject *object)
{
GFdoNotificationBackend *backend = G_FDO_NOTIFICATION_BACKEND (object);
if (backend->bus_name_id)
{
g_bus_unwatch_name (backend->bus_name_id);
backend->bus_name_id = 0;
}
if (backend->notify_subscription)
{
GDBusConnection *session_bus;
session_bus = G_NOTIFICATION_BACKEND (backend)->dbus_connection;
g_dbus_connection_signal_unsubscribe (session_bus, backend->notify_subscription);
backend->notify_subscription = 0;
}
if (backend->notifications)
{
g_slist_free_full (backend->notifications, freedesktop_notification_free);
backend->notifications = NULL;
}
G_OBJECT_CLASS (g_fdo_notification_backend_parent_class)->dispose (object);
}
static gboolean
g_fdo_notification_backend_is_supported (void)
{
/* This is the fallback backend with the lowest priority. To avoid an
* unnecessary synchronous dbus call to check for
* org.freedesktop.Notifications, this function always succeeds. A
* warning will be printed when sending the first notification fails.
*/
return TRUE;
}
static void
g_fdo_notification_backend_send_notification (GNotificationBackend *backend,
const gchar *id,
GNotification *notification)
{
GFdoNotificationBackend *self = G_FDO_NOTIFICATION_BACKEND (backend);
FreedesktopNotification *n, *tmp;
if (self->bus_name_id == 0)
{
self->bus_name_id = g_bus_watch_name_on_connection (backend->dbus_connection,
"org.freedesktop.Notifications",
G_BUS_NAME_WATCHER_FLAGS_NONE,
NULL,
name_vanished_handler_cb,
backend,
NULL);
}
if (self->notify_subscription == 0)
{
self->notify_subscription =
g_dbus_connection_signal_subscribe (backend->dbus_connection,
"org.freedesktop.Notifications",
"org.freedesktop.Notifications", NULL,
"/org/freedesktop/Notifications", NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
notify_signal, backend, NULL);
}
n = freedesktop_notification_new (self, id, notification);
tmp = g_fdo_notification_backend_find_notification (self, id);
if (tmp)
n->notify_id = tmp->notify_id;
call_notify (backend->dbus_connection, backend->application, n->notify_id, notification, notification_sent, n);
}
static void
g_fdo_notification_backend_withdraw_notification (GNotificationBackend *backend,
const gchar *id)
{
GFdoNotificationBackend *self = G_FDO_NOTIFICATION_BACKEND (backend);
FreedesktopNotification *n;
n = g_fdo_notification_backend_find_notification (self, id);
if (n)
{
if (n->notify_id > 0)
{
g_dbus_connection_call (backend->dbus_connection,
"org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
"org.freedesktop.Notifications", "CloseNotification",
g_variant_new ("(u)", n->notify_id), NULL,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
self->notifications = g_slist_remove (self->notifications, n);
freedesktop_notification_free (n);
}
}
static void
g_fdo_notification_backend_init (GFdoNotificationBackend *backend)
{
}
static void
g_fdo_notification_backend_class_init (GFdoNotificationBackendClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GNotificationBackendClass *backend_class = G_NOTIFICATION_BACKEND_CLASS (class);
object_class->dispose = g_fdo_notification_backend_dispose;
backend_class->is_supported = g_fdo_notification_backend_is_supported;
backend_class->send_notification = g_fdo_notification_backend_send_notification;
backend_class->withdraw_notification = g_fdo_notification_backend_withdraw_notification;
}