1 Description: Use synchronous notifications when they are supported
4 Index: gnome-settings-daemon-2.30.0/plugins/common/gsd-osd-notification.c
5 ===================================================================
6 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
7 +++ gnome-settings-daemon-2.30.0/plugins/common/gsd-osd-notification.c 2010-04-23 17:05:08.862133020 +0100
9 +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*- */
11 + * gsd-osd-notification.c
12 + * Copyright (C) 2010 Chris Coulson <chrisccoulson@ubuntu.com>
13 + * Copyright (C) 2009 Canonical Ltd
15 + * gsd-osd-notification.c is free software: you can redistribute it and/or modify it
16 + * under the terms of the GNU General Public License as published by the
17 + * Free Software Foundation, either version 3 of the License, or
18 + * (at your option) any later version.
20 + * gsd-osd-notification.c is distributed in the hope that it will be useful, but
21 + * WITHOUT ANY WARRANTY; without even the implied warranty of
22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 + * See the GNU General Public License for more details.
25 + * You should have received a copy of the GNU General Public License along
26 + * with this program. If not, see <http://www.gnu.org/licenses/>.
29 +#include <libnotify/notify.h>
30 +#include "gsd-osd-notification.h"
32 +struct _GsdOsdNotificationPrivate
34 + NotifyNotification *notification;
37 + guint icon_array_size;
40 +#define GSD_OSD_NOTIFICATION_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_OSD_NOTIFICATION, GsdOsdNotificationPrivate))
49 +static NotifyNotification *icon_only_notification = NULL;
50 +static gulong handler_id;
52 +#define NOTIFY_CAP_PRIVATE_SYNCHRONOUS "x-canonical-private-synchronous"
53 +#define NOTIFY_CAP_PRIVATE_ICON_ONLY "x-canonical-private-icon-only"
54 +#define NOTIFY_HINT_TRUE "true"
56 +G_DEFINE_TYPE (GsdOsdNotification, gsd_osd_notification, G_TYPE_OBJECT);
59 +_calculate_icon (GsdOsdNotification *notifier, guint value, gboolean muted)
63 + s = (notifier->priv->icon_array_size -1) * value / 100 + 1;
65 + s = MIN (s, notifier->priv->icon_array_size -1);
69 + return muted ? notifier->priv->icon_names[0] : notifier->priv->icon_names[s];
73 +gsd_osd_notification_set_icon_array (GsdOsdNotification *notifier, const char **icon_names)
75 + g_return_if_fail (GSD_IS_OSD_NOTIFICATION (notifier));
77 + g_strfreev (notifier->priv->icon_names);
78 + notifier->priv->icon_names = g_strdupv ((gchar **) icon_names);
80 + notifier->priv->icon_array_size = g_strv_length ((gchar **) icon_names);
84 +gsd_osd_notification_set_hint (GsdOsdNotification *notifier, const char *hint)
86 + g_return_if_fail (GSD_IS_OSD_NOTIFICATION (notifier));
88 + g_free (notifier->priv->hint);
89 + notifier->priv->hint = g_strdup (hint);
93 +gsd_osd_notification_is_supported (void)
98 + caps = notify_get_server_caps ();
99 + has_cap = (g_list_find_custom (caps, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, (GCompareFunc) g_strcmp0) != NULL);
100 + g_list_foreach (caps, (GFunc) g_free, NULL);
101 + g_list_free (caps);
107 +notification_closed_cb (NotifyNotification *notification,
110 + g_signal_handler_disconnect (icon_only_notification, handler_id);
111 + g_object_unref (icon_only_notification);
112 + icon_only_notification = NULL;
116 +gsd_osd_notification_show_icon_only (const char *icon, const char *hint)
118 + g_return_val_if_fail (icon != NULL, FALSE);
119 + g_return_val_if_fail (hint != NULL, FALSE);
121 + if (!gsd_osd_notification_is_supported ())
124 + if (icon_only_notification == NULL) {
125 + icon_only_notification = notify_notification_new (" ", "", icon, NULL);
126 + notify_notification_set_hint_string (icon_only_notification, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, hint);
127 + notify_notification_set_hint_string (icon_only_notification, NOTIFY_CAP_PRIVATE_ICON_ONLY, NOTIFY_HINT_TRUE);
128 + handler_id = g_signal_connect (icon_only_notification, "closed", G_CALLBACK (notification_closed_cb), NULL);
130 + notify_notification_set_hint_string (icon_only_notification, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, hint);
131 + notify_notification_update (icon_only_notification, " ", "", icon);
134 + if (!notify_notification_show (icon_only_notification, NULL)) {
135 + g_signal_handler_disconnect (icon_only_notification, handler_id);
136 + g_object_unref (icon_only_notification);
137 + icon_only_notification = NULL;
145 +gsd_osd_notification_show_value (GsdOsdNotification *notifier, gint value, gboolean muted)
149 + g_return_val_if_fail (GSD_IS_OSD_NOTIFICATION (notifier), FALSE);
150 + g_return_val_if_fail (notifier->priv->icon_names != NULL, FALSE);
151 + g_return_val_if_fail (notifier->priv->hint != NULL, FALSE);
153 + if (!gsd_osd_notification_is_supported ())
156 + if (notifier->priv->notification == NULL) {
157 + notifier->priv->notification = notify_notification_new (" ", "", NULL, NULL);
158 + notify_notification_set_hint_string (notifier->priv->notification, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, notifier->priv->hint);
160 + if (notifier->priv->notification != NULL) {
161 + value = MIN (value, 101);
162 + value = MAX (value, -1);
163 + icon = _calculate_icon (notifier, value, muted);
164 + notify_notification_set_hint_int32(notifier->priv->notification, "value", (muted && value > 0) ? 0 : value);
165 + notify_notification_update (notifier->priv->notification, " ", "", icon);
170 + if (!notify_notification_show (notifier->priv->notification, NULL))
177 +gsd_osd_notification_show_overshoot (GsdOsdNotification *notifier, GsdOsdNotifierOvershootType type)
182 + g_return_val_if_fail (type == GSD_OSD_NOTIFICATION_UNDERSHOOT || type == GSD_OSD_NOTIFICATION_OVERSHOOT, FALSE);
186 + case GSD_OSD_NOTIFICATION_UNDERSHOOT:
190 + case GSD_OSD_NOTIFICATION_OVERSHOOT:
195 + g_assert_not_reached ();
199 + return gsd_osd_notification_show_value (notifier, value, muted);
203 +gsd_osd_notification_new (const char **icon_names, const char *hint)
205 + return (GsdOsdNotification *) g_object_new (GSD_TYPE_OSD_NOTIFICATION,
206 + "icon-names", icon_names,
212 +gsd_osd_notification_init (GsdOsdNotification *object)
214 + object->priv = GSD_OSD_NOTIFICATION_PRIVATE (object);
216 + if (!notify_is_initted ())
217 + notify_init (g_get_application_name ());
219 + object->priv->hint = NULL;
220 + object->priv->icon_names = NULL;
221 + object->priv->notification = NULL;
225 +gsd_osd_notification_finalize (GObject *object)
227 + GsdOsdNotification *notifier = GSD_OSD_NOTIFICATION (object);
229 + g_strfreev (notifier->priv->icon_names);
230 + g_free (notifier->priv->hint);
232 + if (notifier->priv->notification)
233 + g_object_unref (notifier->priv->notification);
235 + G_OBJECT_CLASS (gsd_osd_notification_parent_class)->finalize (object);
239 +gsd_osd_notification_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
241 + g_return_if_fail (GSD_IS_OSD_NOTIFICATION (object));
242 + GsdOsdNotification *notifier = GSD_OSD_NOTIFICATION (object);
246 + case PROP_ICON_NAMES:
247 + gsd_osd_notification_set_icon_array (notifier, (const char**) g_value_get_boxed (value));
250 + gsd_osd_notification_set_hint (notifier, g_value_get_string (value));
253 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
259 +gsd_osd_notification_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
261 + g_return_if_fail (GSD_IS_OSD_NOTIFICATION (object));
262 + GsdOsdNotification *notifier = GSD_OSD_NOTIFICATION (object);
266 + case PROP_ICON_NAMES:
267 + g_value_set_boxed (value, notifier->priv->icon_names);
270 + g_value_set_string (value, notifier->priv->hint);
273 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
279 +gsd_osd_notification_class_init (GsdOsdNotificationClass *klass)
281 + GObjectClass* object_class = G_OBJECT_CLASS (klass);
283 + object_class->finalize = gsd_osd_notification_finalize;
284 + object_class->set_property = gsd_osd_notification_set_property;
285 + object_class->get_property = gsd_osd_notification_get_property;
287 + g_object_class_install_property (object_class,
289 + g_param_spec_boxed ("icon-names",
291 + "An array of icon names for the notification",
293 + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
295 + g_object_class_install_property (object_class,
297 + g_param_spec_string ("hint",
298 + "Notification hint",
299 + "Hint for the notification",
301 + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
303 + g_type_class_add_private (klass, sizeof (GsdOsdNotificationPrivate));
305 Index: gnome-settings-daemon-2.30.0/plugins/common/gsd-osd-notification.h
306 ===================================================================
307 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
308 +++ gnome-settings-daemon-2.30.0/plugins/common/gsd-osd-notification.h 2010-04-23 17:05:08.862133020 +0100
310 +/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*- */
312 + * gsd-osd-notification.c
313 + * Copyright (C) 2010 Chris Coulson <chrisccoulson@ubuntu.com>
314 + * Copyright (C) 2009 Canonical Ltd
316 + * gsd-osd-notification.c is free software: you can redistribute it and/or modify it
317 + * under the terms of the GNU General Public License as published by the
318 + * Free Software Foundation, either version 3 of the License, or
319 + * (at your option) any later version.
321 + * gsd-osd-notification.c is distributed in the hope that it will be useful, but
322 + * WITHOUT ANY WARRANTY; without even the implied warranty of
323 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
324 + * See the GNU General Public License for more details.
326 + * You should have received a copy of the GNU General Public License along
327 + * with this program. If not, see <http://www.gnu.org/licenses/>.
330 +#ifndef _GSD_OSD_NOTIFICATION_H_
331 +#define _GSD_OSD_NOTIFICATION_H_
333 +#include <glib-object.h>
337 +#define GSD_TYPE_OSD_NOTIFICATION (gsd_osd_notification_get_type ())
338 +#define GSD_OSD_NOTIFICATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_OSD_NOTIFICATION, GsdOsdNotification))
339 +#define GSD_OSD_NOTIFICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_OSD_NOTIFICATION, GsdOsdNotificationClass))
340 +#define GSD_IS_OSD_NOTIFICATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_OSD_NOTIFICATION))
341 +#define GSD_IS_OSD_NOTIFICATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSD_TYPE_OSD_NOTIFICATION))
342 +#define GSD_OSD_NOTIFICATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSD_TYPE_OSD_NOTIFICATION, GsdOsdNotificationClass))
344 +typedef struct _GsdOsdNotificationClass GsdOsdNotificationClass;
345 +typedef struct _GsdOsdNotification GsdOsdNotification;
346 +typedef struct _GsdOsdNotificationPrivate GsdOsdNotificationPrivate;
348 +struct _GsdOsdNotificationClass
350 + GObjectClass parent_class;
353 +struct _GsdOsdNotification
355 + GObject parent_instance;
357 + GsdOsdNotificationPrivate *priv;
361 + GSD_OSD_NOTIFICATION_NO_OVERSHOOT = 0,
362 + GSD_OSD_NOTIFICATION_UNDERSHOOT,
363 + GSD_OSD_NOTIFICATION_OVERSHOOT,
364 +} GsdOsdNotifierOvershootType;
366 +GType gsd_osd_notification_get_type (void) G_GNUC_CONST;
367 +GsdOsdNotification* gsd_osd_notification_new (const char **icon_names,
369 +void gsd_osd_notification_set_icon_array (GsdOsdNotification *notifier,
370 + const char **icon_names);
371 +void gsd_osd_notification_set_hint (GsdOsdNotification *notifier,
373 +gboolean gsd_osd_notification_is_supported (void);
374 +gboolean gsd_osd_notification_show_value (GsdOsdNotification *notifier,
377 +gboolean gsd_osd_notification_show_overshoot (GsdOsdNotification *notifier,
378 + GsdOsdNotifierOvershootType type);
379 +gboolean gsd_osd_notification_show_icon_only (const char *icon,
384 +#endif /* _GSD_OSD_NOTIFICATION_H_ */
385 Index: gnome-settings-daemon-2.30.0/plugins/media-keys/gsd-media-keys-manager.c
386 ===================================================================
387 --- gnome-settings-daemon-2.30.0.orig/plugins/media-keys/gsd-media-keys-manager.c 2010-03-29 09:15:04.000000000 +0100
388 +++ gnome-settings-daemon-2.30.0/plugins/media-keys/gsd-media-keys-manager.c 2010-04-23 17:05:08.862133020 +0100
390 #include "eggaccelerators.h"
392 #include "gsd-media-keys-window.h"
393 +#include "gsd-osd-notification.h"
396 #include <canberra-gtk.h>
399 GConfClient *conf_client;
400 GVolumeMonitor *volume_monitor;
401 + GsdOsdNotification *notifier;
403 /* Multihead stuff */
404 GdkScreen *current_screen;
407 static gpointer manager_object = NULL;
409 +static const char *volume_icons[] = {
410 + "notification-audio-volume-muted",
411 + "notification-audio-volume-low",
412 + "notification-audio-volume-medium",
413 + "notification-audio-volume-high",
418 init_screens (GsdMediaKeysManager *manager)
419 @@ -612,11 +621,13 @@
422 /* Show the dialogue */
423 - dialog_init (manager);
424 - gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog),
427 - dialog_show (manager);
428 + if (!gsd_osd_notification_show_icon_only ("notification-device-eject", "Eject")) {
429 + dialog_init (manager);
430 + gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog),
433 + dialog_show (manager);
436 /* Clean up the drive selection and exit if no suitable
437 * drives are found */
438 @@ -641,23 +652,44 @@
439 GConfClient *client = manager->priv->conf_client;
440 gboolean state = gconf_client_get_bool (client, TOUCHPAD_ENABLED_KEY, NULL);
442 - dialog_init (manager);
443 - gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog),
444 - (!state) ? "touchpad-enabled" : "touchpad-disabled",
446 - dialog_show (manager);
447 + if (!gsd_osd_notification_show_icon_only ((!state) ? "touchpad-enabled" : "touchpad-disabled", "Touchpad")) {
448 + dialog_init (manager);
449 + gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (manager->priv->dialog),
450 + (!state) ? "touchpad-enabled" : "touchpad-disabled",
452 + dialog_show (manager);
455 gconf_client_set_bool (client, TOUCHPAD_ENABLED_KEY, !state, NULL);
459 +play_volume_event_sound (GtkWidget *widget)
461 + ca_gtk_play_for_widget (widget, 0,
462 + CA_PROP_EVENT_ID, "audio-volume-change",
463 + CA_PROP_EVENT_DESCRIPTION, "volume changed hrough key press",
464 + CA_PROP_APPLICATION_ID, "org.gnome.VolumeControl",
469 update_dialog (GsdMediaKeysManager *manager,
472 - gboolean sound_changed)
473 + gboolean sound_changed,
474 + GsdOsdNotifierOvershootType overshoot)
478 vol = (int) (100 * (double) vol / PA_VOLUME_NORM);
479 + if (overshoot != GSD_OSD_NOTIFICATION_NO_OVERSHOOT) {
480 + if (gsd_osd_notification_show_overshoot (manager->priv->notifier, overshoot))
483 + if (gsd_osd_notification_show_value (manager->priv->notifier, vol, muted))
486 vol = CLAMP (vol, 0, 100);
488 dialog_init (manager);
489 @@ -668,12 +700,18 @@
490 GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME);
491 dialog_show (manager);
493 - if (sound_changed != FALSE && muted == FALSE)
494 - ca_gtk_play_for_widget (manager->priv->dialog, 0,
495 - CA_PROP_EVENT_ID, "audio-volume-change",
496 - CA_PROP_EVENT_DESCRIPTION, "volume changed through key press",
497 - CA_PROP_APPLICATION_ID, "org.gnome.VolumeControl",
500 + if (sound_changed != FALSE && muted == FALSE) {
501 + if (manager->priv->dialog == NULL) {
502 + window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
503 + gtk_window_set_screen (GTK_WINDOW (window), manager->priv->current_screen);
504 + gtk_widget_realize (window);
505 + play_volume_event_sound (window);
506 + gtk_widget_destroy (window);
508 + play_volume_event_sound (manager->priv->dialog);
516 guint vol, norm_vol_step;
518 + GsdOsdNotifierOvershootType overshoot = GSD_OSD_NOTIFICATION_NO_OVERSHOOT;
519 gboolean sound_changed;
521 if (manager->priv->stream == NULL)
523 if (gvc_mixer_stream_set_volume (manager->priv->stream, vol) != FALSE) {
524 gvc_mixer_stream_push_volume (manager->priv->stream);
525 sound_changed = TRUE;
526 + gvc_mixer_stream_push_volume (manager->priv->stream);
529 + overshoot = GSD_OSD_NOTIFICATION_UNDERSHOOT;
533 @@ -750,12 +792,14 @@
534 gvc_mixer_stream_push_volume (manager->priv->stream);
535 sound_changed = TRUE;
538 + overshoot = GSD_OSD_NOTIFICATION_OVERSHOOT;
544 - update_dialog (manager, vol, muted, sound_changed);
545 + update_dialog (manager, vol, muted, sound_changed, overshoot);
552 do_multimedia_player_action (GsdMediaKeysManager *manager,
557 + gsd_osd_notification_show_icon_only (icon, key);
558 return gsd_media_player_key_pressed (manager, key);
561 @@ -972,19 +1019,19 @@
562 execute (manager, "gcalctool", FALSE, FALSE);
565 - return do_multimedia_player_action (manager, "Play");
566 + return do_multimedia_player_action (manager, NULL, "Play");
569 - return do_multimedia_player_action (manager, "Pause");
570 + return do_multimedia_player_action (manager, NULL, "Pause");
573 - return do_multimedia_player_action (manager, "Stop");
574 + return do_multimedia_player_action (manager, NULL, "Stop");
577 - return do_multimedia_player_action (manager, "Previous");
578 + return do_multimedia_player_action (manager, NULL, "Previous");
581 - return do_multimedia_player_action (manager, "Next");
582 + return do_multimedia_player_action (manager, NULL, "Next");
585 g_assert_not_reached ();
586 @@ -1121,6 +1168,8 @@
588 gvc_mixer_control_open (manager->priv->volume);
590 + manager->priv->notifier = gsd_osd_notification_new (volume_icons, "volume");
592 gnome_settings_profile_end ("gvc_mixer_control_new");
593 #endif /* HAVE_PULSE */
594 g_idle_add ((GSourceFunc) start_media_keys_idle_cb, manager);
595 @@ -1218,6 +1267,9 @@
597 g_list_free (priv->media_players);
598 priv->media_players = NULL;
600 + if (manager->priv->notifier != NULL)
601 + g_object_unref (manager->priv->notifier);
605 Index: gnome-settings-daemon-2.30.0/plugins/common/Makefile.am
606 ===================================================================
607 --- gnome-settings-daemon-2.30.0.orig/plugins/common/Makefile.am 2010-03-10 11:59:38.000000000 +0000
608 +++ gnome-settings-daemon-2.30.0/plugins/common/Makefile.am 2010-04-23 17:10:43.209632216 +0100
615 + gsd-osd-notification.c \
616 + gsd-osd-notification.h
618 libcommon_la_CPPFLAGS = \
621 libcommon_la_CFLAGS = \
622 $(SETTINGS_PLUGIN_CFLAGS) \
623 + $(LIBNOTIFY_CFLAGS) \
626 libcommon_la_LDFLAGS = \
627 $(GSD_PLUGIN_LDFLAGS) $(X11_LIBS)
629 libcommon_la_LIBADD = \
630 - $(SETTINGS_PLUGIN_LIBS)
631 + $(SETTINGS_PLUGIN_LIBS) \