1
/* daemon.c - Implementation of the destop notification spec
3
* Awn related modifications by Rodney Cryderman <rcryderman@gmail.com>
5
* Base gnome-notification-daemon by
6
* Copyright (C) 2006 Christian Hammond <chipx86@chipx86.com>
7
* Copyright (C) 2005 John (J5) Palmieri <johnp@redhat.com>
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2, or (at your option)
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
37
#include <sys/types.h>
43
#include <dbus/dbus.h>
44
#include <dbus/dbus-glib.h>
45
#include <glib/gi18n.h>
47
#include <glib-object.h>
49
#include <glib/gprintf.h>
51
#include <libnotify/notify.h>
53
#include <glib/gprintf.h>
55
#include <X11/Xproto.h>
58
#include <X11/Xutil.h>
59
#include <X11/Xatom.h>
65
#define WNCK_I_KNOW_THIS_IS_UNSTABLE
66
#include <libwnck/libwnck.h>
68
#include <sys/types.h>
70
#include <libawn/libawn.h>
76
#include "notificationdaemon-dbus-glue.h"
80
#define NW_GET_NOTIFY_ID(nw) \
81
(GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(nw), "_notify_id")))
82
#define NW_GET_NOTIFY_SENDER(nw) \
83
(g_object_get_data(G_OBJECT(nw), "_notify_sender"))
84
#define NW_GET_DAEMON(nw) \
85
(g_object_get_data(G_OBJECT(nw), "_notify_daemon"))
89
NotifyStackLocation type;
90
const gchar *identifier;
92
} PopupNotifyStackLocation;
98
}AwnNotificationDaemon;
101
Notification_Daemon G_daemon_config;
104
const PopupNotifyStackLocation popup_stack_locations[] =
106
{ NOTIFY_STACK_LOCATION_TOP_LEFT, "top_left" },
107
{ NOTIFY_STACK_LOCATION_TOP_RIGHT, "top_right" },
108
{ NOTIFY_STACK_LOCATION_BOTTOM_LEFT, "bottom_left" },
109
{ NOTIFY_STACK_LOCATION_BOTTOM_RIGHT, "bottom_right" },
110
{ NOTIFY_STACK_LOCATION_AWN, "awn-dynamic" },
111
{ NOTIFY_STACK_LOCATION_UNKNOWN, NULL }
114
#define POPUP_STACK_DEFAULT_INDEX 4 /* XXX Hack! */
118
NotifyDaemon *daemon;
120
GTimeVal paused_diff;
121
gboolean has_timeout;
125
Window src_window_xid;
128
struct _NotifyDaemonPrivate
131
guint timeout_source;
132
GHashTable *idle_reposition_notify_ids;
133
GHashTable *monitored_window_hash;
134
GHashTable *notification_hash;
135
gboolean url_clicked_lock;
136
NotifyStack **stacks;
140
static DesktopAgnosticConfigClient *conf_client = NULL;
142
static DBusConnection *dbus_conn = NULL;
144
#define CHECK_DBUS_VERSION(major, minor) \
145
(DBUS_MAJOR_VER > (major) || \
146
(DBUS_MAJOR_VER == (major) && DBUS_MINOR_VER >= (minor)))
148
#if !CHECK_DBUS_VERSION(0, 60)
149
/* This is a hack that will go away in time. For now, it's fairly safe. */
151
struct _DBusGMethodInvocation
153
DBusGConnection *connection;
154
DBusGMessage *message;
155
const DBusGObjectInfo *object;
156
const DBusGMethodInfo *method;
159
#endif /* D-BUS < 0.60 */
161
static void notify_daemon_finalize(GObject *object);
162
static void _notification_destroyed_cb(GtkWindow *nw, NotifyDaemon *daemon);
163
static void _close_notification(NotifyDaemon *daemon, guint id,
164
gboolean hide_notification,
165
NotifydClosedReason reason);
166
static GdkFilterReturn _notify_x11_filter(GdkXEvent *xevent,
169
static void _emit_closed_signal(GtkWindow *nw, NotifydClosedReason reason);
170
static void _action_invoked_cb(GtkWindow *nw, const char *key);
171
static NotifyStackLocation get_stack_location_from_string(const char *slocation);
172
static void sync_notification_position(NotifyDaemon *daemon, GtkWindow *nw,
174
static void monitor_notification_source_windows(NotifyDaemon *daemon,
178
G_DEFINE_TYPE(NotifyDaemon, notify_daemon, G_TYPE_OBJECT);
181
notify_daemon_class_init(NotifyDaemonClass *daemon_class)
183
GObjectClass *object_class = G_OBJECT_CLASS(daemon_class);
185
object_class->finalize = notify_daemon_finalize;
187
g_type_class_add_private(daemon_class, sizeof(NotifyDaemonPrivate));
191
_notify_timeout_destroy(NotifyTimeout *nt)
194
* Disconnect the destroy handler to avoid a loop since the id
195
* won't be removed from the hash table before the widget is
198
g_signal_handlers_disconnect_by_func(nt->nw, _notification_destroyed_cb,
201
gtk_widget_destroy(GTK_WIDGET(nt->nw));
206
notify_daemon_init(NotifyDaemon *daemon)
208
NotifyStackLocation location;
209
DesktopAgnosticConfigClient *client = get_conf_client();
215
daemon->priv = G_TYPE_INSTANCE_GET_PRIVATE(daemon, NOTIFY_TYPE_DAEMON,
216
NotifyDaemonPrivate);
218
daemon->priv->next_id = 1;
219
daemon->priv->timeout_source = 0;
221
// slocation = gconf_client_get_string(client, GCONF_KEY_POPUP_LOCATION, NULL);
222
slocation = g_strdup ("bottom_right");
224
location = get_stack_location_from_string(slocation);
227
display = gdk_display_get_default();
228
screen = gdk_display_get_default_screen(display);
229
daemon->priv->stacks_size = gdk_screen_get_n_monitors(screen);
230
daemon->priv->stacks = g_new0(NotifyStack *, daemon->priv->stacks_size);
232
daemon->priv->idle_reposition_notify_ids = g_hash_table_new(NULL, NULL);
233
daemon->priv->monitored_window_hash = g_hash_table_new(NULL, NULL);
234
gdk_window_add_filter(NULL, _notify_x11_filter, daemon);
236
for (i = 0; i < daemon->priv->stacks_size; i++)
238
daemon->priv->stacks[i] = notify_stack_new(daemon, screen,
242
daemon->priv->notification_hash =
244
g_hash_table_new_full(g_int_hash, g_int_equal, g_free,
245
(GDestroyNotify)_notify_timeout_destroy);
248
/*awn daemon specific initialization follows*/
252
notify_daemon_finalize(GObject *object)
254
NotifyDaemon *daemon = NOTIFY_DAEMON(object);
255
GObjectClass *parent_class = G_OBJECT_CLASS(notify_daemon_parent_class);
257
g_hash_table_destroy(daemon->priv->monitored_window_hash);
258
g_hash_table_destroy(daemon->priv->idle_reposition_notify_ids);
259
g_hash_table_destroy(daemon->priv->notification_hash);
260
g_free(daemon->priv);
262
if (parent_class->finalize != NULL)
263
parent_class->finalize(object);
266
static NotifyStackLocation
267
get_stack_location_from_string(const char *slocation)
269
NotifyStackLocation stack_location = NOTIFY_STACK_LOCATION_DEFAULT;
271
if (slocation == NULL || *slocation == '\0')
272
return NOTIFY_STACK_LOCATION_DEFAULT;
275
const PopupNotifyStackLocation *l;
277
for (l = popup_stack_locations;
278
l->type != NOTIFY_STACK_LOCATION_UNKNOWN;
281
if (!strcmp(slocation, l->identifier))
282
stack_location = l->type;
286
return stack_location;
290
create_signal(GtkWindow *nw, const char *signal_name)
292
guint id = NW_GET_NOTIFY_ID(nw);
293
gchar *dest = NW_GET_NOTIFY_SENDER(nw);
294
DBusMessage *message;
296
g_assert(dest != NULL);
298
message = dbus_message_new_signal("/org/freedesktop/Notifications",
299
"org.freedesktop.Notifications",
302
dbus_message_set_destination(message, dest);
303
dbus_message_append_args(message,
304
DBUS_TYPE_UINT32, &id,
311
_action_invoked_cb(GtkWindow *nw, const char *key)
313
NotifyDaemon *daemon = NW_GET_DAEMON(nw);
314
guint id = NW_GET_NOTIFY_ID(nw);
315
DBusMessage *message;
317
message = create_signal(nw, "ActionInvoked");
318
dbus_message_append_args(message,
319
DBUS_TYPE_STRING, &key,
322
dbus_connection_send(dbus_conn, message, NULL);
323
dbus_message_unref(message);
325
_close_notification(daemon, id, TRUE, NOTIFYD_CLOSED_USER);
329
_emit_closed_signal(GtkWindow *nw, NotifydClosedReason reason)
331
DBusMessage *message = create_signal(nw, "NotificationClosed");
332
dbus_message_append_args(message,
333
DBUS_TYPE_UINT32, &reason,
335
dbus_connection_send(dbus_conn, message, NULL);
336
dbus_message_unref(message);
340
_close_notification(NotifyDaemon *daemon, guint id,
341
gboolean bhide_notification, NotifydClosedReason reason)
343
NotifyDaemonPrivate *priv = daemon->priv;
346
nt = (NotifyTimeout *)g_hash_table_lookup(priv->notification_hash, &id);
350
_emit_closed_signal(nt->nw, reason);
352
if (bhide_notification)
353
hide_notification(nt->nw);
355
g_hash_table_remove(priv->notification_hash, &id);
360
_notification_destroyed_cb(GtkWindow *nw, NotifyDaemon *daemon)
363
* This usually won't happen, but can if notification-daemon dies before
364
* all notifications are closed. Mark them as expired.
366
_close_notification(daemon, NW_GET_NOTIFY_ID(nw), FALSE,
367
NOTIFYD_CLOSED_EXPIRED);
372
NotifyDaemon *daemon;
374
} IdleRepositionData;
377
idle_reposition_notification(gpointer datap)
379
IdleRepositionData *data = (IdleRepositionData *)datap;
380
NotifyDaemon *daemon = data->daemon;
384
notify_id = data->id;
386
/* Look up the timeout, if it's completed we don't need to do anything */
387
nt = (NotifyTimeout *)g_hash_table_lookup(daemon->priv->notification_hash,
390
sync_notification_position(daemon, nt->nw, nt->src_window_xid);
393
g_hash_table_remove(daemon->priv->idle_reposition_notify_ids,
394
GINT_TO_POINTER(notify_id));
395
g_object_unref(daemon);
402
_queue_idle_reposition_notification(NotifyDaemon *daemon, gint notify_id)
404
IdleRepositionData *data;
409
/* Do we already have an idle update pending? */
410
if (g_hash_table_lookup_extended(daemon->priv->idle_reposition_notify_ids,
411
GINT_TO_POINTER(notify_id),
417
data = g_new0(IdleRepositionData, 1);
418
data->daemon = g_object_ref(daemon);
419
data->id = notify_id;
421
/* We do this as a short timeout to avoid repositioning spam */
422
idle_id = g_timeout_add_full(G_PRIORITY_LOW, 50,
423
idle_reposition_notification, data, NULL);
424
g_hash_table_insert(daemon->priv->idle_reposition_notify_ids,
425
GINT_TO_POINTER(notify_id), GUINT_TO_POINTER(idle_id));
428
static GdkFilterReturn
429
_notify_x11_filter(GdkXEvent *xevent,
433
NotifyDaemon *daemon = NOTIFY_DAEMON(user_data);
434
XEvent *xev = (XEvent *)xevent;
440
if (xev->xany.type == DestroyNotify)
442
g_hash_table_remove(daemon->priv->monitored_window_hash,
443
GUINT_TO_POINTER(xev->xany.window));
444
return GDK_FILTER_CONTINUE;
447
if (!g_hash_table_lookup_extended(daemon->priv->monitored_window_hash,
448
GUINT_TO_POINTER(xev->xany.window), &orig_key, &value))
449
return GDK_FILTER_CONTINUE;
451
notify_id = GPOINTER_TO_INT(value);
453
if (xev->xany.type == ConfigureNotify || xev->xany.type == MapNotify)
455
_queue_idle_reposition_notification(daemon, notify_id);
457
else if (xev->xany.type == ReparentNotify)
459
nt = (NotifyTimeout *)g_hash_table_lookup(
460
daemon->priv->notification_hash, ¬ify_id);
463
return GDK_FILTER_CONTINUE;
466
* If the window got reparented, we need to start monitoring the
469
monitor_notification_source_windows(daemon, nt, nt->src_window_xid);
470
sync_notification_position(daemon, nt->nw, nt->src_window_xid);
473
return GDK_FILTER_CONTINUE;
477
_mouse_entered_cb(GtkWindow *nw, GdkEventCrossing *event, NotifyDaemon *daemon)
483
if (event->detail == GDK_NOTIFY_INFERIOR)
486
id = NW_GET_NOTIFY_ID(nw);
488
nt = (NotifyTimeout *)g_hash_table_lookup(daemon->priv->notification_hash,
493
g_get_current_time(&now);
495
nt->paused_diff.tv_usec = nt->expiration.tv_usec - now.tv_usec;
497
nt->paused_diff.tv_sec = nt->expiration.tv_sec - now.tv_sec;
499
if (nt->paused_diff.tv_usec < 0)
501
nt->paused_diff.tv_usec += G_USEC_PER_SEC;
502
nt->paused_diff.tv_sec--;
507
_mouse_exitted_cb(GtkWindow *nw, GdkEventCrossing *event,
508
NotifyDaemon *daemon)
513
if (event->detail == GDK_NOTIFY_INFERIOR)
516
id = NW_GET_NOTIFY_ID(nw);
518
nt = (NotifyTimeout *)g_hash_table_lookup(daemon->priv->notification_hash,
525
_is_expired(gpointer key, gpointer value, gpointer data)
527
NotifyTimeout *nt = (NotifyTimeout *)value;
528
gboolean *phas_more_timeouts = (gboolean *)data;
530
time_t expiration_time;
533
if (!nt->has_timeout)
536
g_get_current_time(&now);
538
expiration_time = (nt->expiration.tv_sec * 1000) +
539
(nt->expiration.tv_usec / 1000);
541
now_time = (now.tv_sec * 1000) + (now.tv_usec / 1000);
543
if (now_time > expiration_time)
545
notification_tick(nt->nw, 0);
546
_emit_closed_signal(nt->nw, NOTIFYD_CLOSED_EXPIRED);
551
nt->expiration.tv_usec = nt->paused_diff.tv_usec + now.tv_usec;
552
nt->expiration.tv_sec = nt->paused_diff.tv_sec + now.tv_sec;
554
if (nt->expiration.tv_usec >= G_USEC_PER_SEC)
556
nt->expiration.tv_usec -= G_USEC_PER_SEC;
557
nt->expiration.tv_sec++;
562
notification_tick(nt->nw, expiration_time - now_time);
565
*phas_more_timeouts = TRUE;
571
_check_expiration(gpointer data)
573
NotifyDaemon *daemon = (NotifyDaemon *)data;
574
gboolean has_more_timeouts = FALSE;
576
g_hash_table_foreach_remove(daemon->priv->notification_hash,
577
_is_expired, (gpointer)&has_more_timeouts);
579
if (!has_more_timeouts)
580
daemon->priv->timeout_source = 0;
582
return has_more_timeouts;
586
_calculate_timeout(NotifyDaemon *daemon, NotifyTimeout *nt, int timeout)
589
nt->has_timeout = FALSE;
594
if (G_daemon_config.timeout > 0)
595
timeout = G_daemon_config.timeout;
597
nt->has_timeout = TRUE;
600
timeout = NOTIFY_DAEMON_DEFAULT_TIMEOUT;
602
set_notification_timeout(nt->nw, timeout);
604
usec = timeout * 1000; /* convert from msec to usec */
607
* If it's less than 0, wrap around back to MAXLONG.
608
* g_time_val_add() requires a glong, and anything larger than
609
* MAXLONG will be treated as a negative value.
614
g_get_current_time(&nt->expiration);
616
g_time_val_add(&nt->expiration, usec);
618
if (daemon->priv->timeout_source == 0)
620
daemon->priv->timeout_source =
621
g_timeout_add(100, _check_expiration, daemon);
626
static NotifyTimeout *
627
_store_notification(NotifyDaemon *daemon, GtkWindow *nw, int timeout)
629
NotifyDaemonPrivate *priv = daemon->priv;
642
if (g_hash_table_lookup(priv->notification_hash, &id) != NULL)
648
nt = g_new0(NotifyTimeout, 1);
653
_calculate_timeout(daemon, nt, timeout);
655
g_hash_table_insert(priv->notification_hash,
656
g_memdup(&id, sizeof(guint)), nt);
662
_notify_daemon_process_icon_data(NotifyDaemon *daemon, GtkWindow *nw,
665
const guchar *data = NULL;
674
GValueArray *image_struct;
677
#if CHECK_DBUS_VERSION(0, 61)
680
struct_type = dbus_g_type_get_struct(
688
dbus_g_type_get_collection("GArray", G_TYPE_UCHAR),
691
if (!G_VALUE_HOLDS(icon_data, struct_type))
693
g_warning("_notify_daemon_process_icon_data expected a "
694
"GValue of type GValueArray");
698
#endif /* D-BUS >= 0.61 */
700
image_struct = (GValueArray *)g_value_get_boxed(icon_data);
702
value = g_value_array_get_nth(image_struct, 0);
706
g_warning("_notify_daemon_process_icon_data expected position "
707
"0 of the GValueArray to exist");
711
if (!G_VALUE_HOLDS(value, G_TYPE_INT))
713
g_warning("_notify_daemon_process_icon_data expected "
714
"position 0 of the GValueArray to be of type int");
718
width = g_value_get_int(value);
720
value = g_value_array_get_nth(image_struct, 1);
724
g_warning("_notify_daemon_process_icon_data expected "
725
"position 1 of the GValueArray to exist");
729
if (!G_VALUE_HOLDS(value, G_TYPE_INT))
731
g_warning("_notify_daemon_process_icon_data expected "
732
"position 1 of the GValueArray to be of type int");
736
height = g_value_get_int(value);
738
value = g_value_array_get_nth(image_struct, 2);
742
g_warning("_notify_daemon_process_icon_data expected "
743
"position 2 of the GValueArray to exist");
747
if (!G_VALUE_HOLDS(value, G_TYPE_INT))
749
g_warning("_notify_daemon_process_icon_data expected "
750
"position 2 of the GValueArray to be of type int");
754
rowstride = g_value_get_int(value);
756
value = g_value_array_get_nth(image_struct, 3);
760
g_warning("_notify_daemon_process_icon_data expected "
761
"position 3 of the GValueArray to exist");
765
if (!G_VALUE_HOLDS(value, G_TYPE_BOOLEAN))
767
g_warning("_notify_daemon_process_icon_data expected "
768
"position 3 of the GValueArray to be of type gboolean");
772
has_alpha = g_value_get_boolean(value);
774
value = g_value_array_get_nth(image_struct, 4);
778
g_warning("_notify_daemon_process_icon_data expected "
779
"position 4 of the GValueArray to exist");
783
if (!G_VALUE_HOLDS(value, G_TYPE_INT))
785
g_warning("_notify_daemon_process_icon_data expected "
786
"position 4 of the GValueArray to be of type int");
790
bits_per_sample = g_value_get_int(value);
792
value = g_value_array_get_nth(image_struct, 5);
796
g_warning("_notify_daemon_process_icon_data expected "
797
"position 5 of the GValueArray to exist");
801
if (!G_VALUE_HOLDS(value, G_TYPE_INT))
803
g_warning("_notify_daemon_process_icon_data expected "
804
"position 5 of the GValueArray to be of type int");
808
n_channels = g_value_get_int(value);
810
value = g_value_array_get_nth(image_struct, 6);
814
g_warning("_notify_daemon_process_icon_data expected "
815
"position 6 of the GValueArray to exist");
819
if (!G_VALUE_HOLDS(value,
820
dbus_g_type_get_collection("GArray", G_TYPE_UCHAR)))
822
g_warning("_notify_daemon_process_icon_data expected "
823
"position 6 of the GValueArray to be of type GArray");
827
tmp_array = (GArray *)g_value_get_boxed(value);
829
expected_len = (height - 1) * rowstride + width *
830
((n_channels * bits_per_sample + 7) / 8);
832
if (expected_len != tmp_array->len)
834
g_warning("_notify_daemon_process_icon_data expected image "
835
"data to be of length %" G_GSIZE_FORMAT " but got a "
837
expected_len, tmp_array->len);
841
data = (guchar *)g_memdup(tmp_array->data, tmp_array->len);
843
pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, has_alpha,
844
bits_per_sample, width, height,
846
(GdkPixbufDestroyNotify)g_free,
848
set_notification_icon(nw, pixbuf);
849
g_object_unref(G_OBJECT(pixbuf));
855
window_clicked_cb(GtkWindow *nw, GdkEventButton *button, NotifyDaemon *daemon)
857
if (daemon->priv->url_clicked_lock)
859
daemon->priv->url_clicked_lock = FALSE;
863
_action_invoked_cb(nw, "default");
865
_close_notification(daemon, NW_GET_NOTIFY_ID(nw), TRUE,
866
NOTIFYD_CLOSED_USER);
870
popup_location_changed_cb(DesktopAgnosticConfigClient *client, guint cnxn_id,
871
gpointer *entry, gpointer user_data)
873
NotifyDaemon *daemon = (NotifyDaemon*)user_data;
874
NotifyStackLocation stack_location;
875
const char *slocation;
881
stack_location = NOTIFY_STACK_LOCATION_DEFAULT;
883
for (i = 0; i < daemon->priv->stacks_size; i++)
884
notify_stack_set_location(daemon->priv->stacks[i], stack_location);
888
url_clicked_cb(GtkWindow *nw, const char *url)
890
NotifyDaemon *daemon = NW_GET_DAEMON(nw);
894
/* Somewhat of a hack.. */
895
daemon->priv->url_clicked_lock = TRUE;
897
escaped_url = g_shell_quote(url);
900
* We can't actually check for GNOME_DESKTOP_SESSION_ID, because it's
901
* not in the environment for this program :(
904
if (/*g_getenv("GNOME_DESKTOP_SESSION_ID") != NULL &&*/
905
g_find_program_in_path("gnome-open") != NULL)
907
cmd = g_strdup_printf("gnome-open %s", escaped_url);
909
else if (g_find_program_in_path("mozilla-firefox") != NULL)
911
cmd = g_strdup_printf("mozilla-firefox %s", escaped_url);
913
else if (g_find_program_in_path("firefox") != NULL)
915
cmd = g_strdup_printf("firefox %s", escaped_url);
917
else if (g_find_program_in_path("mozilla") != NULL)
919
cmd = g_strdup_printf("mozilla %s", escaped_url);
923
g_warning("Unable to find a browser.");
930
g_spawn_command_line_async(cmd, NULL);
936
screensaver_active(GtkWidget *nw)
938
GdkDisplay *display = gdk_drawable_get_display(GDK_DRAWABLE(nw->window));
941
unsigned long nitems, bytes_after;
942
unsigned char *temp_data;
943
gboolean active = FALSE;
944
Atom XA_BLANK = gdk_x11_get_xatom_by_name_for_display(display, "BLANK");
945
Atom XA_LOCK = gdk_x11_get_xatom_by_name_for_display(display, "LOCK");
947
/* Check for a screensaver first. */
949
if (XGetWindowProperty(
950
GDK_DISPLAY_XDISPLAY(display),
952
gdk_x11_get_xatom_by_name_for_display(display, "_SCREENSAVER_STATUS"),
953
0, G_MAXLONG, False, XA_INTEGER, &type, &format, &nitems,
954
&bytes_after, &temp_data) == Success &&
955
type && temp_data != NULL)
957
CARD32 *data = (CARD32 *)temp_data;
959
active = (type == XA_INTEGER && nitems >= 3 &&
960
(time_t)data[1] > (time_t)666000000L &&
961
(data[0] == XA_BLANK || data[0] == XA_LOCK));
964
if (temp_data != NULL)
970
fullscreen_window_exists(GtkWidget *nw)
972
WnckScreen *wnck_screen;
973
WnckWorkspace *wnck_workspace;
976
wnck_screen = wnck_screen_get(GDK_SCREEN_XNUMBER(
977
gdk_drawable_get_screen(GDK_DRAWABLE(GTK_WIDGET(nw)->window))));
978
wnck_screen_force_update(wnck_screen);
980
wnck_workspace = wnck_screen_get_active_workspace(wnck_screen);
982
for (l = wnck_screen_get_windows_stacked(wnck_screen);
986
WnckWindow *wnck_win = (WnckWindow *)l->data;
988
if (wnck_window_is_on_workspace(wnck_win, wnck_workspace) &&
989
wnck_window_is_fullscreen(wnck_win) &&
990
wnck_window_is_active(wnck_win))
993
* Sanity check if the window is _really_ fullscreen to
994
* work around a bug in libwnck that doesn't get all
995
* unfullscreen events.
997
int sw = wnck_screen_get_width(wnck_screen);
998
int sh = wnck_screen_get_height(wnck_screen);
1001
wnck_window_get_geometry(wnck_win, &x, &y, &w, &h);
1003
if (sw == w && sh == h)
1012
get_window_parent(Display *display,
1017
Window *children = NULL;
1021
gdk_error_trap_push();
1022
result = XQueryTree(display, window, root, &parent, &children, &nchildren);
1023
if (gdk_error_trap_pop() || !result)
1033
* Recurse over X Window and parents, up to root, and start watching them
1034
* for position changes.
1037
monitor_notification_source_windows(NotifyDaemon *daemon,
1041
Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
1045
/* Store the window in the timeout */
1046
g_assert(nt != NULL);
1047
nt->src_window_xid = source;
1049
for (parent = get_window_parent(display, source, &root);
1050
parent != None && root != parent;
1051
parent = get_window_parent(display, parent, &root)) {
1053
XSelectInput(display, parent, StructureNotifyMask);
1054
g_hash_table_insert(daemon->priv->monitored_window_hash,
1055
GUINT_TO_POINTER(parent), GINT_TO_POINTER(nt->id));
1059
/* Use a source X Window ID to reposition a notification. */
1061
sync_notification_position(NotifyDaemon *daemon,
1065
Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
1070
unsigned int width, height;
1071
unsigned int border_width, depth;
1073
gdk_error_trap_push();
1075
/* Get the root for this window */
1076
result = XGetGeometry(display, source, &root, &x, &y,
1077
&width, &height, &border_width, &depth);
1078
if (gdk_error_trap_pop() || !result)
1082
* Now calculate the offset coordinates for the source window from
1085
gdk_error_trap_push ();
1086
result = XTranslateCoordinates(display, source, root, 0, 0,
1088
if (gdk_error_trap_pop() || !result)
1095
* We need to manually queue a draw here as the default theme recalculates
1096
* its position in the draw handler and moves the window (which seems
1097
* fairly broken), so just calling move/show above isn't enough to cause
1098
* its position to be calculated.
1100
gtk_widget_queue_draw(GTK_WIDGET(nw));
1104
notify_daemon_error_quark(void)
1106
static GQuark q = 0;
1109
q = g_quark_from_static_string("notification-daemon-error-quark");
1115
notify_daemon_notify_handler(NotifyDaemon *daemon,
1116
const gchar *app_name,
1119
const gchar *summary,
1123
int timeout, DBusGMethodInvocation *context)
1125
NotifyDaemonPrivate *priv = daemon->priv;
1126
NotifyTimeout *nt = NULL;
1127
GtkWindow *nw = NULL;
1129
gboolean use_pos_data = FALSE;
1130
gboolean new_notification = FALSE;
1133
Window window_xid = None;
1136
gchar *sound_file = NULL;
1137
gboolean sound_enabled;
1142
nt = (NotifyTimeout *)g_hash_table_lookup(priv->notification_hash,
1153
nw = create_notification(url_clicked_cb);
1154
g_object_set_data(G_OBJECT(nw), "_notify_daemon", daemon);
1155
gtk_widget_realize(GTK_WIDGET(nw));
1156
new_notification = TRUE;
1158
g_signal_connect(G_OBJECT(nw), "button-release-event",
1159
G_CALLBACK(window_clicked_cb), daemon);
1160
g_signal_connect(G_OBJECT(nw), "destroy",
1161
G_CALLBACK(_notification_destroyed_cb), daemon);
1162
g_signal_connect(G_OBJECT(nw), "enter-notify-event",
1163
G_CALLBACK(_mouse_entered_cb), daemon);
1164
g_signal_connect(G_OBJECT(nw), "leave-notify-event",
1165
G_CALLBACK(_mouse_exitted_cb), daemon);
1169
clear_notification_actions(nw);
1172
set_notification_text(nw, summary, body);
1174
set_notification_hints(nw, hints);
1177
*XXX This needs to handle file URIs and all that.
1181
if ((data = (GValue *)g_hash_table_lookup(hints, "window-xid")) != NULL)
1183
window_xid = (Window)g_value_get_uint(data);
1185
/* deal with x, and y hints */
1186
else if ((data = (GValue *)g_hash_table_lookup(hints, "x")) != NULL)
1188
x = g_value_get_int(data);
1190
if ((data = (GValue *)g_hash_table_lookup(hints, "y")) != NULL)
1192
y = g_value_get_int(data);
1193
use_pos_data = TRUE;
1197
/* Deal with sound hints */
1199
sound_enabled = desktop_agnostic_config_client_get_bool (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,"sound_enabled",NULL);
1201
data = (GValue *)g_hash_table_lookup(hints, "suppress-sound");
1205
if (G_VALUE_HOLDS_BOOLEAN(data))
1206
sound_enabled = !g_value_get_boolean(data);
1207
else if (G_VALUE_HOLDS_INT(data))
1208
sound_enabled = (g_value_get_int(data) != 0);
1211
g_warning("suppress-sound is of type %s (expected bool or int)\n",
1212
g_type_name(G_VALUE_TYPE(data)));
1218
data = (GValue *)g_hash_table_lookup(hints, "sound-file");
1222
sound_file = g_value_dup_string(data);
1224
if (*sound_file == '\0' ||
1225
!g_file_test(sound_file, G_FILE_TEST_EXISTS))
1233
* TODO: If we don't have a sound_file yet, get the urgency hint, then
1234
* get the corresponding system event sound
1236
* We will need to parse /etc/sound/events/gnome-2.soundlist
1237
* and ~/.gnome2/sound/events/gnome-2.soundlist.
1240
/* If we don't have a sound file yet, use our gconf default */
1241
if (sound_file == NULL)
1243
sound_file = desktop_agnostic_config_client_get_string (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,"default_sound",NULL);
1244
if (sound_file != NULL &&
1245
(*sound_file == '\0' ||
1246
!g_file_test(sound_file, G_FILE_TEST_EXISTS)))
1254
/* set up action buttons */
1255
for (i = 0; actions[i] != NULL; i += 2)
1257
gchar *l = actions[i + 1];
1261
g_warning("Label not found for action %s. "
1262
"The protocol specifies that a label must "
1263
"follow an action in the actions array", actions[i]);
1268
if (strcasecmp(actions[i], "default"))
1270
add_notification_action(nw, l, actions[i],
1271
G_CALLBACK(_action_invoked_cb));
1275
/* check for icon_data if icon == "" */
1278
data = (GValue *)g_hash_table_lookup(hints, "icon_data");
1281
_notify_daemon_process_icon_data(daemon, nw, data);
1285
GdkPixbuf *pixbuf = NULL;
1287
if (!strncmp(icon, "file://", 7) || *icon == '/')
1289
if (!strncmp(icon, "file://", 7))
1293
pixbuf = gdk_pixbuf_new_from_file(icon, NULL);
1297
/* Load icon theme icon */
1298
GtkIconTheme *theme = gtk_icon_theme_get_default();
1299
GtkIconInfo *icon_info =
1300
gtk_icon_theme_lookup_icon(theme, icon, IMAGE_SIZE,
1301
GTK_ICON_LOOKUP_USE_BUILTIN);
1303
if (icon_info != NULL)
1305
gint icon_size = MIN(IMAGE_SIZE,
1306
gtk_icon_info_get_base_size(icon_info));
1309
icon_size = IMAGE_SIZE;
1311
pixbuf = gtk_icon_theme_load_icon(theme, icon, icon_size,
1312
GTK_ICON_LOOKUP_USE_BUILTIN,
1315
gtk_icon_info_free(icon_info);
1320
/* Well... maybe this is a file afterall. */
1321
pixbuf = gdk_pixbuf_new_from_file(icon, NULL);
1327
set_notification_icon(nw, pixbuf);
1328
g_object_unref(G_OBJECT(pixbuf));
1332
if (window_xid != None && G_daemon_config.awn_client_pos)
1335
* Do nothing here if we were passed an XID; we'll call
1336
* sync_notification_position later.
1339
else if (use_pos_data && G_daemon_config.awn_client_pos)
1342
* Typically, the theme engine will set its own position based on
1343
* the arrow X, Y hints. However, in case, move the notification to
1346
set_notification_arrow(GTK_WIDGET(nw), TRUE, x, y);
1347
move_notification(GTK_WIDGET(nw), x, y);
1354
set_notification_arrow(GTK_WIDGET(nw), FALSE, 0, 0);
1356
gdk_display_get_pointer(gdk_display_get_default(),
1357
&screen, &x, &y, NULL);
1358
monitor = gdk_screen_get_monitor_at_point(screen, x, y);
1359
g_assert(monitor >= 0 && monitor < priv->stacks_size);
1361
notify_stack_add_window(priv->stacks[monitor], nw, new_notification);
1366
nt = _store_notification(daemon, nw, timeout);
1373
* If we have a source Window XID, start monitoring the tree
1374
* for changes, and reposition the window based on the source
1375
* window. We need to do this after return_id is calculated.
1377
if (window_xid != None && G_daemon_config.awn_client_pos)
1379
monitor_notification_source_windows(daemon, nt, window_xid);
1380
sync_notification_position(daemon, nw, window_xid);
1383
if (!screensaver_active(GTK_WIDGET(nw)) &&
1384
!fullscreen_window_exists(GTK_WIDGET(nw)))
1386
show_notification(nw);
1388
if (sound_file != NULL)
1389
sound_play(sound_file);
1394
#if CHECK_DBUS_VERSION(0, 60)
1395
sender = dbus_g_method_get_sender(context);
1397
sender = g_strdup(dbus_message_get_sender(
1398
dbus_g_message_get_message(context->message)));
1401
g_object_set_data(G_OBJECT(nw), "_notify_id",
1402
GUINT_TO_POINTER(return_id));
1403
g_object_set_data_full(G_OBJECT(nw), "_notify_sender", sender,
1404
(GDestroyNotify)g_free);
1407
_calculate_timeout(daemon, nt, timeout);
1409
dbus_g_method_return(context, return_id);
1415
notify_daemon_close_notification_handler(NotifyDaemon *daemon,
1416
guint id, GError **error)
1420
g_set_error(error, notify_daemon_error_quark(), 100,
1421
_("%u is not a valid notification ID"), id);
1426
_close_notification(daemon, id, TRUE, NOTIFYD_CLOSED_API);
1432
notify_daemon_get_capabilities(NotifyDaemon *daemon, char ***caps)
1434
*caps = g_new0(char *, 6);
1436
(*caps)[0] = g_strdup("actions");
1437
(*caps)[1] = g_strdup("body");
1438
(*caps)[2] = g_strdup("body-hyperlinks");
1439
(*caps)[3] = g_strdup("body-markup");
1440
(*caps)[4] = g_strdup("icon-static");
1447
notify_daemon_get_server_information(NotifyDaemon *daemon,
1451
char **out_spec_ver)
1453
*out_name = g_strdup("Notification Daemon");
1454
*out_vendor = g_strdup("Galago Project");
1455
*out_version = g_strdup(VERSION);
1456
*out_spec_ver = g_strdup("1.0");
1461
DesktopAgnosticConfigClient *
1462
get_conf_client(void)
1468
_height_changed(AwnApplet *app, guint height, gpointer *data)
1472
gboolean _do_wait(gpointer null)
1474
return (waitpid(-1, NULL, WNOHANG) <= 0) ;
1478
gboolean send_message(gchar *body)
1480
NotifyNotification *notify;
1481
gchar *summary = "Awn Notification Daemon Message";
1483
gchar *icon_str = NULL;
1484
glong expire_timeout = NOTIFY_EXPIRES_DEFAULT;
1485
NotifyUrgency urgency = NOTIFY_URGENCY_NORMAL;
1489
notify_init("notify-send");
1490
notify = notify_notification_new(summary, body, icon_str, NULL);
1491
notify_notification_set_category(notify, type);
1492
notify_notification_set_urgency(notify, urgency);
1493
notify_notification_set_timeout(notify, expire_timeout);
1494
notify_notification_show(notify, NULL);
1496
g_object_unref(G_OBJECT(notify));
1501
g_timeout_add(3000, (GSourceFunc)_do_wait, NULL);
1506
gboolean hide_icon(gpointer data)
1509
gtk_widget_set_size_request(GTK_WIDGET(G_daemon_config.awn_app), 1, 1);
1510
gtk_widget_hide(GTK_WIDGET(G_daemon_config.awn_app));
1511
// g_object_unref(G_daemon_config.awn_icon);
1513
G_daemon_config.awn_icon = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 1, 1);
1514
gdk_pixbuf_fill(G_daemon_config.awn_icon, 0x00000000);
1515
awn_applet_simple_set_icon_pixbuf(AWN_APPLET_SIMPLE(G_daemon_config.awn_app), G_daemon_config.awn_icon);
1516
// g_object_unref(G_daemon_config.awn_icon);
1517
G_daemon_config.awn_icon = NULL;
1523
config_get_color(DesktopAgnosticConfigClient *client, gchar * group,const gchar *key, DesktopAgnosticColor **color)
1525
GError *error = NULL;
1526
GValue value = {0,};
1528
desktop_agnostic_config_client_get_value(client, group, key, &value, &error);
1532
g_warning("Notification Daemon: error reading config string (%s): %s", key, error->message);
1533
g_error_free(error);
1534
*color = desktop_agnostic_color_new_from_string("#000", NULL);
1538
*color = (DesktopAgnosticColor*)g_value_dup_object(&value);
1539
g_value_unset(&value);
1543
static void read_config(void)
1545
static gboolean done_once = FALSE;
1547
static DesktopAgnosticConfigClient * theme_client = NULL;
1548
GError * error = NULL;
1552
theme_client = awn_config_get_default (AWN_PANEL_ID_DEFAULT,NULL);
1555
if (desktop_agnostic_config_client_get_bool (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_KILL_ND,NULL))
1559
DBusGConnection *connection;
1561
connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
1564
g_warning ("Unable to make connection to the D-Bus session bus: %s",
1566
g_error_free (error);
1571
proxy = dbus_g_proxy_new_for_name (connection,
1572
"org.freedesktop.DBus",
1573
"/org/freedesktop/DBus",
1574
"org.freedesktop.DBus");
1576
dbus_g_proxy_call (proxy, "GetConnectionUnixProcessID", &error,
1577
G_TYPE_STRING, "org.freedesktop.Notifications",
1584
kill ((pid_t)pid,SIGTERM);
1586
dbus_g_connection_unref(connection);
1590
g_object_unref (proxy);
1595
G_daemon_config.awn_client_pos = desktop_agnostic_config_client_get_bool (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_CLIENT_POS,NULL);
1597
G_daemon_config.awn_use_theme = desktop_agnostic_config_client_get_bool (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_HONOUR_GTK,NULL);
1599
if (G_daemon_config.awn_use_theme)
1601
config_get_color (theme_client, "theme","gstep2",&G_daemon_config.awn_bg);
1602
if ( (double)desktop_agnostic_color_get_alpha (G_daemon_config.awn_bg)/(double)0xFFFF < 0.80)
1604
desktop_agnostic_color_set_alpha (G_daemon_config.awn_bg, 0xFFFF * 0.8);
1607
if ( desktop_agnostic_config_client_get_int (theme_client,"theme","icon_font_mode",NULL) == 2)
1609
config_get_color (theme_client, "theme","icon_text_outline_color",&G_daemon_config.awn_text);
1613
config_get_color (theme_client, "theme","icon_text_color",&G_daemon_config.awn_text);
1615
if (!G_daemon_config.awn_text)
1617
G_daemon_config.awn_text = desktop_agnostic_color_new_from_string ("white",NULL);
1619
G_daemon_config.awn_text_str = desktop_agnostic_color_to_string (G_daemon_config.awn_text);
1621
gchar * tmp = g_strdup (G_daemon_config.awn_text_str+1);
1622
g_free (G_daemon_config.awn_text_str);
1623
G_daemon_config.awn_text_str = tmp;
1625
if (strlen(G_daemon_config.awn_text_str) > 6)
1626
G_daemon_config.awn_text_str[6] = '\0';
1628
config_get_color (theme_client, "theme","ghistep2",&G_daemon_config.awn_border);
1632
config_get_color (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_BG,&G_daemon_config.awn_bg);
1634
config_get_color (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_TEXT_COLOUR,&G_daemon_config.awn_text);
1636
G_daemon_config.awn_text_str = desktop_agnostic_color_to_string (G_daemon_config.awn_text);
1638
gchar * tmp = g_strdup (G_daemon_config.awn_text_str+1);
1639
g_free (G_daemon_config.awn_text_str);
1640
G_daemon_config.awn_text_str = tmp;
1642
if (strlen(G_daemon_config.awn_text_str) > 6)
1643
G_daemon_config.awn_text_str[6] = '\0';
1645
config_get_color (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_BG,&G_daemon_config.awn_border);
1647
G_daemon_config.awn_border_width = desktop_agnostic_config_client_get_int (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_BORDER_WIDTH,NULL);
1649
G_daemon_config.awn_gradient_factor = desktop_agnostic_config_client_get_float (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_GRADIENT_FACTOR,NULL);
1651
G_daemon_config.awn_override_x = desktop_agnostic_config_client_get_int (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_OVERRIDE_X,NULL);
1653
G_daemon_config.awn_override_y = desktop_agnostic_config_client_get_int (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_OVERRIDE_Y,NULL);
1655
G_daemon_config.timeout = desktop_agnostic_config_client_get_int (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_TIMEOUT,NULL);
1657
G_daemon_config.bold_text_body = desktop_agnostic_config_client_get_bool (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_BOLD_BODY,NULL);
1659
G_daemon_config.show_icon = desktop_agnostic_config_client_get_bool (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_SHOW_ICON,NULL);
1661
G_daemon_config.hide_opacity = desktop_agnostic_config_client_get_float (conf_client, DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,GCONF_KEY_AWN_HIDE_OPACITY,NULL);
1666
_change_config_cb(const gchar *group, const gchar *key, const GValue *value, gpointer user_data)
1669
g_debug ("%s",__func__);
1672
static gboolean _button_clicked_event(GtkWidget *widget, GdkEventButton *event, void * null)
1674
static GtkWidget *menu=NULL;
1675
G_daemon_config.show_status = !G_daemon_config.show_status;
1676
if (event->button == 1)
1678
if (G_daemon_config.show_status)
1680
// gdk_pixbuf_fill(G_daemon_config.awn_icon, 0xdddddd33);
1681
awn_applet_simple_set_icon_state(AWN_APPLET_SIMPLE(G_daemon_config.awn_app),"On");
1685
// gdk_pixbuf_fill(G_daemon_config.awn_icon, 0x00000033);
1686
awn_applet_simple_set_icon_state(AWN_APPLET_SIMPLE(G_daemon_config.awn_app),"Off");
1689
// awn_applet_simple_set_icon(AWN_APPLET_SIMPLE(G_daemon_config.awn_app), G_daemon_config.awn_icon);
1691
else if (event->button == 3)
1695
menu = awn_applet_create_default_menu (G_daemon_config.awn_app);
1696
gtk_menu_set_screen (GTK_MENU (menu), NULL);
1698
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
1699
event->button, event->time);
1704
AwnApplet* awn_applet_factory_initp(const gchar *name,
1705
const gchar *uid, gint panel_id)
1707
NotifyDaemon *daemon;
1708
DBusGConnection *connection;
1709
DBusGProxy *bus_proxy;
1711
guint request_name_result;
1713
DesktopAgnosticConfigClient * theme_client = NULL;
1715
G_daemon_config.awn_app = applet = AWN_APPLET(awn_applet_simple_new(name, uid, panel_id));
1716
theme_client = awn_config_get_default (AWN_PANEL_ID_DEFAULT, &error);
1718
gint height = awn_applet_get_size(applet);
1720
G_daemon_config.awn_app_height = height;
1721
G_daemon_config.show_status = TRUE;
1723
g_object_set (applet,
1724
"display-name","Awn Notification Daemon",
1727
g_signal_connect(G_OBJECT(applet), "size-changed", G_CALLBACK(_height_changed), (gpointer)applet);
1728
gtk_widget_set_size_request(GTK_WIDGET(applet), height, height);
1731
G_daemon_config.awn_icon = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, height, height);
1732
gdk_pixbuf_fill(G_daemon_config.awn_icon, 0xdddddd33);
1733
awn_applet_simple_set_icon(AWN_APPLET_SIMPLE(applet), G_daemon_config.awn_icon);
1736
gchar * states[]={"On","Off",NULL};
1737
gchar * icon_names[]={"stock_up","stock_down",NULL};
1738
awn_applet_simple_set_icon_info(AWN_APPLET_SIMPLE(applet),
1742
awn_applet_simple_set_icon_state (AWN_APPLET_SIMPLE(applet),"On");
1743
/* awn_applet_simple_set_icon_name (AWN_APPLET_SIMPLE(applet),
1744
"Awn Notification Daemon",
1746
/* gtk_widget_show_all(GTK_WIDGET(applet));*/
1749
g_log_set_always_fatal(G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
1753
conf_client = awn_config_get_default_for_applet(AWN_APPLET(applet), NULL);
1759
connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
1761
while (connection == NULL)
1763
printf("Failed to open connection to bus: %s. sleeping 5 s.\n",
1765
g_error_free(error);
1766
connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
1770
dbus_conn = dbus_g_connection_get_connection(connection);
1774
dbus_g_object_type_install_info(NOTIFY_TYPE_DAEMON,
1775
&dbus_glib_notification_daemon_object_info);
1777
bus_proxy = dbus_g_proxy_new_for_name(connection,
1778
"org.freedesktop.DBus",
1779
"/org/freedesktop/DBus",
1780
"org.freedesktop.DBus");
1783
while (!dbus_g_proxy_call(bus_proxy, "RequestName", &error,
1784
G_TYPE_STRING, "org.freedesktop.Notifications",
1787
G_TYPE_UINT, &request_name_result,
1790
printf("Could not aquire name: %s. sleeping 2 seconds", error->message);
1794
daemon = g_object_new(NOTIFY_TYPE_DAEMON, NULL);
1798
desktop_agnostic_config_client_notify_add(conf_client,
1799
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1800
GCONF_KEY_AWN_KILL_ND,
1801
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1804
desktop_agnostic_config_client_notify_add(conf_client,
1805
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1807
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1810
desktop_agnostic_config_client_notify_add(conf_client,
1811
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1812
GCONF_KEY_AWN_BORDER,
1813
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1816
desktop_agnostic_config_client_notify_add(conf_client,
1817
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1818
GCONF_KEY_AWN_BORDER_WIDTH,
1819
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1822
desktop_agnostic_config_client_notify_add(conf_client,
1823
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1824
GCONF_KEY_AWN_GRADIENT_FACTOR,
1825
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1828
desktop_agnostic_config_client_notify_add(conf_client,
1829
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1830
GCONF_KEY_AWN_TEXT_COLOUR,
1831
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1834
desktop_agnostic_config_client_notify_add(conf_client,
1835
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1836
GCONF_KEY_AWN_CLIENT_POS,
1837
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1840
desktop_agnostic_config_client_notify_add(conf_client,
1841
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1842
GCONF_KEY_AWN_HONOUR_GTK,
1843
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1846
desktop_agnostic_config_client_notify_add(conf_client,
1847
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1848
GCONF_KEY_AWN_OVERRIDE_X,
1849
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1852
desktop_agnostic_config_client_notify_add(conf_client,
1853
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1854
GCONF_KEY_AWN_OVERRIDE_Y,
1855
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1858
desktop_agnostic_config_client_notify_add(conf_client,
1859
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1860
GCONF_KEY_AWN_TIMEOUT,
1861
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1864
desktop_agnostic_config_client_notify_add(conf_client,
1865
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1866
GCONF_KEY_AWN_BOLD_BODY,
1867
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1870
desktop_agnostic_config_client_notify_add(conf_client,
1871
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1872
GCONF_KEY_AWN_SHOW_ICON,
1873
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1876
desktop_agnostic_config_client_notify_add(conf_client,
1877
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1878
GCONF_KEY_AWN_HIDE_OPACITY,
1879
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1882
desktop_agnostic_config_client_notify_add(conf_client,
1883
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1885
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1888
desktop_agnostic_config_client_notify_add(conf_client,
1889
DESKTOP_AGNOSTIC_CONFIG_GROUP_DEFAULT,
1891
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1894
desktop_agnostic_config_client_notify_add(theme_client,
1897
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1900
desktop_agnostic_config_client_notify_add(theme_client,
1903
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1906
desktop_agnostic_config_client_notify_add(theme_client,
1908
"icon_text_outline_color",
1909
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1912
desktop_agnostic_config_client_notify_add(theme_client,
1915
(DesktopAgnosticConfigNotifyFunc)_change_config_cb,
1918
/* just chopping crap out converting to lda */
1919
popup_location_changed_cb(conf_client, 0,NULL, daemon);
1921
dbus_g_connection_register_g_object(connection, "/org/freedesktop/Notifications", G_OBJECT(daemon));
1923
// g_timeout_add(5000, (GSourceFunc)send_message, g_strdup("Awn Notification Daemon has loaded Successfully.\nClick <a href=\"http://wiki.awn-project.org/index.php?title=Awn_Notification-Daemon\">Here</a> for online documentation."));
1925
if (! G_daemon_config.show_icon)
1927
g_timeout_add(3000, (GSourceFunc)hide_icon, NULL);
1931
g_signal_connect(G_OBJECT(G_daemon_config.awn_app), "button-press-event", G_CALLBACK(_button_clicked_event), NULL);