[Galago-commits] r2890 - in trunk/notification-daemon: . src
galago-commits at freedesktop.org
galago-commits at freedesktop.org
Sun Jul 30 14:23:50 PDT 2006
Author: chipx86
Date: 2006-07-30 14:23:40 -0700 (Sun, 30 Jul 2006)
New Revision: 2890
Added:
trunk/notification-daemon/src/stack.c
trunk/notification-daemon/src/stack.h
Modified:
trunk/notification-daemon/ChangeLog
trunk/notification-daemon/src/Makefile.am
trunk/notification-daemon/src/daemon.c
trunk/notification-daemon/src/daemon.h
Log:
Add the beginning of what should be working multi-monitor support. Popups should now appear on the monitor that the mouse cursor is on.
Modified: trunk/notification-daemon/ChangeLog
===================================================================
--- trunk/notification-daemon/ChangeLog 2006-07-30 04:40:40 UTC (rev 2889)
+++ trunk/notification-daemon/ChangeLog 2006-07-30 21:23:40 UTC (rev 2890)
@@ -1,3 +1,13 @@
+Sun Jul 30 14:22:47 PDT 2006 Christian Hammond <chipx86 at chipx86.com>
+
+ * src/Makefile.am:
+ * src/daemon.c:
+ * src/daemon.h:
+ A src/stack.c:
+ A src/stack.h:
+ - Add the beginning of what should be working multi-monitor support.
+ Popups should now appear on the monitor that the mouse cursor is on.
+
Sat Jul 29 21:00:45 PDT 2006 Christian Hammond <chipx86 at chipx86.com>
* src/daemon.c:
Modified: trunk/notification-daemon/src/Makefile.am
===================================================================
--- trunk/notification-daemon/src/Makefile.am 2006-07-30 04:40:40 UTC (rev 2889)
+++ trunk/notification-daemon/src/Makefile.am 2006-07-30 21:23:40 UTC (rev 2890)
@@ -1,10 +1,12 @@
libexec_PROGRAMS = notification-daemon
notification_daemon_SOURCES = \
+ daemon.c \
+ daemon.h \
engines.c \
engines.h \
- daemon.c \
- daemon.h
+ stack.c \
+ stack.h
notification_daemon_LDADD = $(NOTIFICATION_DAEMON_LIBS)
Modified: trunk/notification-daemon/src/daemon.c
===================================================================
--- trunk/notification-daemon/src/daemon.c 2006-07-30 04:40:40 UTC (rev 2889)
+++ trunk/notification-daemon/src/daemon.c 2006-07-30 21:23:40 UTC (rev 2890)
@@ -44,6 +44,7 @@
#include "daemon.h"
#include "engines.h"
+#include "stack.h"
#include "notificationdaemon-dbus-glue.h"
#define IMAGE_SIZE 48
@@ -55,54 +56,41 @@
#define NW_GET_DAEMON(nw) \
(g_object_get_data(G_OBJECT(nw), "_notify_daemon"))
-typedef enum
+typedef struct
{
- POPUP_STACK_LOCATION_UNKNOWN = -1,
- POPUP_STACK_LOCATION_TOP_LEFT,
- POPUP_STACK_LOCATION_TOP_RIGHT,
- POPUP_STACK_LOCATION_BOTTOM_LEFT,
- POPUP_STACK_LOCATION_BOTTOM_RIGHT,
- POPUP_STACK_LOCATION_DEFAULT = POPUP_STACK_LOCATION_BOTTOM_RIGHT
+ NotifyStackLocation type;
+ const gchar *identifier;
-} PopupStackLocationType;
+} PopupNotifyStackLocation;
-struct PopupStackLocation
+const PopupNotifyStackLocation popup_stack_locations[] =
{
- PopupStackLocationType type;
- const gchar *identifier;
+ { NOTIFY_STACK_LOCATION_TOP_LEFT, "top_left" },
+ { NOTIFY_STACK_LOCATION_TOP_RIGHT, "top_right" },
+ { NOTIFY_STACK_LOCATION_BOTTOM_LEFT, "bottom_left" },
+ { NOTIFY_STACK_LOCATION_BOTTOM_RIGHT, "bottom_right" },
+ { NOTIFY_STACK_LOCATION_UNKNOWN, NULL }
};
-const struct PopupStackLocation popup_stack_locations[] =
+typedef struct
{
- { POPUP_STACK_LOCATION_TOP_LEFT, "top_left" },
- { POPUP_STACK_LOCATION_TOP_RIGHT, "top_right" },
- { POPUP_STACK_LOCATION_BOTTOM_LEFT, "bottom_left" },
- { POPUP_STACK_LOCATION_BOTTOM_RIGHT, "bottom_right" },
- { POPUP_STACK_LOCATION_UNKNOWN, NULL }
-};
-
-struct _NotifyTimeout
-{
GTimeVal expiration;
GTimeVal paused_diff;
gboolean has_timeout;
gboolean paused;
guint id;
-
GtkWindow *nw;
-};
-typedef struct _NotifyTimeout NotifyTimeout;
+} NotifyTimeout;
struct _NotifyDaemonPrivate
{
guint next_id;
guint timeout_source;
GHashTable *notification_hash;
- GSList *poptart_stack;
gboolean url_clicked_lock;
- gboolean stack_only;
- PopupStackLocationType popup_stack_location;
+ NotifyStack **stacks;
+ gint stacks_size;
};
static GConfClient *gconf_client = NULL;
@@ -124,12 +112,11 @@
#endif /* D-BUS < 0.60 */
static void notify_daemon_finalize(GObject *object);
-static void _update_stack_location_from_string(NotifyDaemon *daemon,
- const char *slocation);
static void _close_notification(NotifyDaemon *daemon, guint id,
gboolean hide_notification);
static void _emit_closed_signal(GtkWindow *nw);
static void _action_invoked_cb(GtkWindow *nw, const char *key);
+static NotifyStackLocation get_stack_location_from_string(const char *slocation);
G_DEFINE_TYPE(NotifyDaemon, notify_daemon, G_TYPE_OBJECT);
@@ -153,21 +140,35 @@
static void
notify_daemon_init(NotifyDaemon *daemon)
{
+ NotifyStackLocation location;
GConfClient *client = get_gconf_client();
+ GdkDisplay *display;
+ GdkScreen *screen;
gchar *slocation;
+ gint i;
daemon->priv = G_TYPE_INSTANCE_GET_PRIVATE(daemon, NOTIFY_TYPE_DAEMON,
NotifyDaemonPrivate);
daemon->priv->next_id = 1;
daemon->priv->timeout_source = 0;
- daemon->priv->stack_only = FALSE;
slocation = gconf_client_get_string(client, GCONF_KEY_POPUP_LOCATION,
NULL);
- update_stack_location_from_string(daemon, slocation);
+ location = get_stack_location_from_string(slocation);
g_free(slocation);
+ display = gdk_display_get_default();
+ screen = gdk_display_get_default_screen(display);
+ daemon->priv->stacks_size = gdk_screen_get_n_monitors(screen);
+ daemon->priv->stacks = g_new0(NotifyStack *, daemon->priv->stacks_size);
+
+ for (i = 0; i < daemon->priv->stacks_size; i++)
+ {
+ daemon->priv->stacks[i] = notify_stack_new(daemon, screen,
+ i, location);
+ }
+
daemon->priv->notification_hash =
g_hash_table_new_full(g_int_hash, g_int_equal, g_free,
(GDestroyNotify)_notify_timeout_destroy);
@@ -180,41 +181,33 @@
GObjectClass *parent_class = G_OBJECT_CLASS(notify_daemon_parent_class);
g_hash_table_destroy(daemon->priv->notification_hash);
- g_slist_free(daemon->priv->poptart_stack);
g_free(daemon->priv);
if (parent_class->finalize != NULL)
parent_class->finalize(object);
}
-static void
-update_stack_location_from_string(NotifyDaemon *daemon, const char *slocation)
+static NotifyStackLocation
+get_stack_location_from_string(const char *slocation)
{
+ NotifyStackLocation stack_location = NOTIFY_STACK_LOCATION_DEFAULT;
+
if (slocation != NULL && *slocation != '\0')
+ return NOTIFY_STACK_LOCATION_DEFAULT;
+ else
{
- PopupStackLocationType location_type = POPUP_STACK_LOCATION_DEFAULT;
- const struct PopupStackLocation *l;
+ const PopupNotifyStackLocation *l;
for (l = popup_stack_locations;
- l->type != POPUP_STACK_LOCATION_UNKNOWN;
+ l->type != NOTIFY_STACK_LOCATION_UNKNOWN;
l++)
{
if (!strcmp(slocation, l->identifier))
- location_type = l->type;
+ stack_location = l->type;
}
-
- if (location_type != POPUP_STACK_LOCATION_UNKNOWN)
- daemon->priv->popup_stack_location = location_type;
}
- else
- {
- gconf_client_set_string(get_gconf_client(),
- "/apps/notification-daemon/popup_location",
- popup_stack_locations[POPUP_STACK_LOCATION_DEFAULT].identifier,
- NULL);
- daemon->priv->popup_stack_location = POPUP_STACK_LOCATION_DEFAULT;
- }
+ return stack_location;
}
static DBusMessage *
@@ -658,238 +651,38 @@
_close_notification(daemon, NW_GET_NOTIFY_ID(nw), TRUE);
}
-static gboolean
-get_work_area(GtkWidget *nw, GdkRectangle *rect)
-{
- Atom workarea = XInternAtom(GDK_DISPLAY(), "_NET_WORKAREA", True);
- Atom type;
- Window win;
- int format;
- gulong num, leftovers;
- gulong max_len = 4 * 32;
- guchar *ret_workarea;
- long *workareas;
- int result;
- GdkScreen *screen;
- int disp_screen;
-
- gtk_widget_realize(nw);
- screen = gdk_drawable_get_screen(GDK_DRAWABLE(nw->window));
- disp_screen = GDK_SCREEN_XNUMBER(screen);
-
- /* Defaults in case of error */
- rect->x = 0;
- rect->y = 0;
- rect->width = gdk_screen_get_width(screen);
- rect->height = gdk_screen_get_height(screen);
-
- if (workarea == None)
- return FALSE;
-
- win = XRootWindow(GDK_DISPLAY(), disp_screen);
- result = XGetWindowProperty(GDK_DISPLAY(), win, workarea, 0,
- max_len, False, AnyPropertyType,
- &type, &format, &num, &leftovers,
- &ret_workarea);
-
- if (result != Success || type == None || format == 0 || leftovers ||
- num % 4)
- {
- return FALSE;
- }
-
- workareas = (long *)ret_workarea;
- rect->x = workareas[disp_screen * 4];
- rect->y = workareas[disp_screen * 4 + 1];
- rect->width = workareas[disp_screen * 4 + 2];
- rect->height = workareas[disp_screen * 4 + 3];
-
- XFree(ret_workarea);
-
- return TRUE;
-}
-
static void
-_pop_stack_get_origin_coordinates(PopupStackLocationType location_type,
- GdkRectangle workarea,
- gint *x, gint *y, gint *shx, gint *shy,
- const gint width, const gint height)
-{
- switch (location_type)
- {
- case POPUP_STACK_LOCATION_TOP_LEFT:
- *x = workarea.x;
- *y = workarea.y;
- *shy = height;
- break;
-
- case POPUP_STACK_LOCATION_TOP_RIGHT:
- *x = workarea.x + workarea.width - width;
- *y = workarea.y;
- *shy = height;
- break;
-
- case POPUP_STACK_LOCATION_BOTTOM_LEFT:
- *x = workarea.x;
- *y = workarea.y + workarea.height - height;
- break;
-
- case POPUP_STACK_LOCATION_BOTTOM_RIGHT:
- *x = workarea.x + workarea.width - width;
- *y = workarea.y + workarea.height - height;
- break;
-
- default:
- g_assert_not_reached();
- }
-}
-
-static void
-_pop_stack_translate_coordinates(PopupStackLocationType location_type,
- GdkRectangle workarea,
- gint *x, gint *y, gint *shx, gint *shy,
- const gint width, const gint height,
- const gint index)
-{
- switch (location_type)
- {
- case POPUP_STACK_LOCATION_TOP_LEFT:
- *x = workarea.x;
- *y += *shy;
- *shy = height;
- break;
-
- case POPUP_STACK_LOCATION_TOP_RIGHT:
- *x = workarea.x + workarea.width - width;
- *y += *shy;
- *shy = height;
- break;
-
- case POPUP_STACK_LOCATION_BOTTOM_LEFT:
- *x = workarea.x;
- *y -= height;
- break;
-
- case POPUP_STACK_LOCATION_BOTTOM_RIGHT:
- *x = workarea.x + workarea.width - width;
- *y -= height;
- break;
-
- default:
- g_assert_not_reached();
- }
-}
-
-static void
popup_location_changed_cb(GConfClient *client, guint cnxn_id,
GConfEntry *entry, gpointer user_data)
{
NotifyDaemon *daemon = (NotifyDaemon*)user_data;
+ NotifyStackLocation stack_location;
+ const char *slocation;
GConfValue *value;
+ gint i;
if (daemon == NULL)
return;
value = gconf_entry_get_value(entry);
- update_stack_location_from_string(
- daemon,
- value != NULL ? gconf_value_get_string(value) : NULL);
-}
+ slocation = (value != NULL ? gconf_value_get_string(value) : NULL);
-static void
-_remove_bubble_from_poptart_stack(GtkWindow *nw, NotifyDaemon *daemon)
-{
- NotifyDaemonPrivate *priv = daemon->priv;
- GdkRectangle workarea;
- GSList *remove_link = NULL;
- GSList *link;
- gint x, y, shiftx = 0, shifty = 0, index = 0;
-
- get_work_area(GTK_WIDGET(nw), &workarea);
-
- _pop_stack_get_origin_coordinates(priv->popup_stack_location,
- workarea, &x, &y, &shiftx, &shifty,
- 0, 0);
-
- for (link = priv->poptart_stack; link != NULL; link = link->next)
+ if (slocation != NULL && *slocation != '\0')
{
- GtkWindow *nw2 = link->data;
- GtkRequisition req;
-
- if (nw2 != nw)
- {
- gtk_widget_size_request(GTK_WIDGET(nw2), &req);
-
- _pop_stack_translate_coordinates(priv->popup_stack_location,
- workarea, &x, &y,
- &shiftx, &shifty,
- req.width, req.height,
- index++);
-
- theme_move_notification(nw2, x, y);
- }
- else
- {
- remove_link = link;
- }
+ stack_location = get_stack_location_from_string(slocation);
}
-
- if (remove_link)
+ else
{
- priv->poptart_stack = g_slist_remove_link(priv->poptart_stack,
- remove_link);
- }
+ gconf_client_set_string(get_gconf_client(),
+ "/apps/notification-daemon/popup_location",
+ popup_stack_locations[NOTIFY_STACK_LOCATION_DEFAULT].identifier,
+ NULL);
- if (GTK_WIDGET_REALIZED(GTK_WIDGET(nw)))
- gtk_widget_unrealize(GTK_WIDGET(nw));
-}
-
-static void
-_notify_daemon_add_bubble_to_poptart_stack(NotifyDaemon *daemon,
- GtkWindow *nw,
- gboolean new_notification)
-{
- NotifyDaemonPrivate *priv = daemon->priv;
- GtkRequisition req;
- GdkRectangle workarea;
- GSList *link;
- gint x, y, shiftx = 0, shifty = 0, index = 1;
-
- gtk_widget_size_request(GTK_WIDGET(nw), &req);
-
- get_work_area(GTK_WIDGET(nw), &workarea);
-
- _pop_stack_get_origin_coordinates(priv->popup_stack_location, workarea,
- &x, &y, &shiftx, &shifty,
- req.width, req.height);
-
- theme_move_notification(nw, x, y);
-
- for (link = priv->poptart_stack; link != NULL; link = link->next)
- {
- GtkWindow *nw2 = GTK_WINDOW(link->data);
-
- if (nw2 != nw)
- {
- gtk_widget_size_request(GTK_WIDGET(nw2), &req);
-
- _pop_stack_translate_coordinates(priv->popup_stack_location,
- workarea, &x, &y,
- &shiftx, &shifty,
- req.width, req.height,
- index++);
-
- theme_move_notification(nw2, x, y);
- }
+ stack_location = NOTIFY_STACK_LOCATION_DEFAULT;
}
- if (new_notification)
- {
- g_signal_connect(G_OBJECT(nw), "destroy",
- G_CALLBACK(_remove_bubble_from_poptart_stack),
- daemon);
- priv->poptart_stack = g_slist_prepend(priv->poptart_stack, nw);
- }
+ for (i = 0; i < daemon->priv->stacks_size; i++)
+ notify_stack_set_location(daemon->priv->stacks[i], stack_location);
}
static void
@@ -1174,9 +967,18 @@
}
else
{
+ gint monitor;
+ GdkScreen *screen;
+ gint x, y;
+
theme_set_notification_arrow(nw, FALSE, 0, 0);
- _notify_daemon_add_bubble_to_poptart_stack(daemon, nw,
- new_notification);
+
+ gdk_display_get_pointer(gdk_display_get_default(),
+ &screen, &x, &y, NULL);
+ monitor = gdk_screen_get_monitor_at_point(screen, x, y);
+ g_assert(monitor >= 0 && monitor < priv->stacks_size);
+
+ notify_stack_add_window(priv->stacks[monitor], nw, new_notification);
}
if (!screensaver_active(GTK_WIDGET(nw)) &&
Modified: trunk/notification-daemon/src/daemon.h
===================================================================
--- trunk/notification-daemon/src/daemon.h 2006-07-30 04:40:40 UTC (rev 2889)
+++ trunk/notification-daemon/src/daemon.h 2006-07-30 21:23:40 UTC (rev 2890)
@@ -33,8 +33,6 @@
#define GCONF_KEY_THEME GCONF_KEY_DAEMON "/theme"
#define GCONF_KEY_POPUP_LOCATION GCONF_KEY_DAEMON "/popup_location"
-G_BEGIN_DECLS
-
#define NOTIFY_TYPE_DAEMON (notify_daemon_get_type())
#define NOTIFY_DAEMON(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), NOTIFY_TYPE_DAEMON, NotifyDaemon))
@@ -71,6 +69,8 @@
NOTIFY_DAEMON_ERROR_GENERIC = 0,
};
+G_BEGIN_DECLS
+
GType notify_daemon_get_type(void);
NotifyDaemon *notify_daemon_new(void)
Added: trunk/notification-daemon/src/stack.c
===================================================================
--- trunk/notification-daemon/src/stack.c 2006-07-30 04:40:40 UTC (rev 2889)
+++ trunk/notification-daemon/src/stack.c 2006-07-30 21:23:40 UTC (rev 2890)
@@ -0,0 +1,279 @@
+/*
+ * stack.c - Notification stack groups.
+ *
+ * Copyright (C) 2006 Christian Hammond <chipx86 at chipx86.com>
+ *
+ * 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, 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 "config.h"
+#include "engines.h"
+#include "stack.h"
+
+#include <X11/Xproto.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <gdk/gdkx.h>
+
+struct _NotifyStack
+{
+ NotifyDaemon *daemon;
+ GdkScreen *screen;
+ guint monitor;
+ NotifyStackLocation location;
+ GSList *windows;
+};
+
+static gboolean
+get_work_area(GtkWidget *nw, GdkRectangle *rect)
+{
+ Atom workarea = XInternAtom(GDK_DISPLAY(), "_NET_WORKAREA", True);
+ Atom type;
+ Window win;
+ int format;
+ gulong num, leftovers;
+ gulong max_len = 4 * 32;
+ guchar *ret_workarea;
+ long *workareas;
+ int result;
+ GdkScreen *screen;
+ int disp_screen;
+
+ gtk_widget_realize(nw);
+ screen = gdk_drawable_get_screen(GDK_DRAWABLE(nw->window));
+ disp_screen = GDK_SCREEN_XNUMBER(screen);
+
+ /* Defaults in case of error */
+ rect->x = 0;
+ rect->y = 0;
+ rect->width = gdk_screen_get_width(screen);
+ rect->height = gdk_screen_get_height(screen);
+
+ if (workarea == None)
+ return FALSE;
+
+ win = XRootWindow(GDK_DISPLAY(), disp_screen);
+ result = XGetWindowProperty(GDK_DISPLAY(), win, workarea, 0,
+ max_len, False, AnyPropertyType,
+ &type, &format, &num, &leftovers,
+ &ret_workarea);
+
+ if (result != Success || type == None || format == 0 || leftovers ||
+ num % 4)
+ {
+ return FALSE;
+ }
+
+ workareas = (long *)ret_workarea;
+ rect->x = workareas[disp_screen * 4];
+ rect->y = workareas[disp_screen * 4 + 1];
+ rect->width = workareas[disp_screen * 4 + 2];
+ rect->height = workareas[disp_screen * 4 + 3];
+
+ XFree(ret_workarea);
+
+ return TRUE;
+}
+
+static void
+get_origin_coordinates(NotifyStackLocation stack_location,
+ GdkRectangle workarea,
+ gint *x, gint *y, gint *shiftx, gint *shifty,
+ gint width, gint height)
+{
+ switch (stack_location)
+ {
+ case NOTIFY_STACK_LOCATION_TOP_LEFT:
+ *x = workarea.x;
+ *y = workarea.y;
+ *shifty = height;
+ break;
+
+ case NOTIFY_STACK_LOCATION_TOP_RIGHT:
+ *x = workarea.x + workarea.width - width;
+ *y = workarea.y;
+ *shifty = height;
+ break;
+
+ case NOTIFY_STACK_LOCATION_BOTTOM_LEFT:
+ *x = workarea.x;
+ *y = workarea.y + workarea.height - height;
+ break;
+
+ case NOTIFY_STACK_LOCATION_BOTTOM_RIGHT:
+ *x = workarea.x + workarea.width - width;
+ *y = workarea.y + workarea.height - height;
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void
+translate_coordinates(NotifyStackLocation stack_location,
+ GdkRectangle workarea,
+ gint *x, gint *y, gint *shiftx, gint *shifty,
+ gint width, gint height, gint index)
+{
+ switch (stack_location)
+ {
+ case NOTIFY_STACK_LOCATION_TOP_LEFT:
+ *x = workarea.x;
+ *y += *shifty;
+ *shifty = height;
+ break;
+
+ case NOTIFY_STACK_LOCATION_TOP_RIGHT:
+ *x = workarea.x + workarea.width - width;
+ *y += *shifty;
+ *shifty = height;
+ break;
+
+ case NOTIFY_STACK_LOCATION_BOTTOM_LEFT:
+ *x = workarea.x;
+ *y -= height;
+ break;
+
+ case NOTIFY_STACK_LOCATION_BOTTOM_RIGHT:
+ *x = workarea.x + workarea.width - width;
+ *y -= height;
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
+}
+
+NotifyStack *
+notify_stack_new(NotifyDaemon *daemon,
+ GdkScreen *screen,
+ guint monitor,
+ NotifyStackLocation location)
+{
+ NotifyStack *stack;
+
+ g_assert(daemon != NULL);
+ g_assert(screen != NULL && GDK_IS_SCREEN(screen));
+ g_assert(monitor < gdk_screen_get_n_monitors(screen));
+ g_assert(location != NOTIFY_STACK_LOCATION_UNKNOWN);
+
+ stack = g_new0(NotifyStack, 1);
+ stack->daemon = daemon;
+ stack->screen = screen;
+ stack->monitor = monitor;
+ stack->location = location;
+
+ return stack;
+}
+
+void
+notify_stack_destroy(NotifyStack *stack)
+{
+ g_assert(stack != NULL);
+
+ g_slist_free(stack->windows);
+ g_free(stack);
+}
+
+void
+notify_stack_set_location(NotifyStack *stack,
+ NotifyStackLocation location)
+{
+ stack->location = location;
+}
+
+void
+notify_stack_add_window(NotifyStack *stack,
+ GtkWindow *nw,
+ gboolean new_notification)
+{
+ GtkRequisition req;
+ GdkRectangle workarea;
+ GSList *l;
+ gint x, y, shiftx = 0, shifty = 0, index = 1;
+
+ gtk_widget_size_request(GTK_WIDGET(nw), &req);
+
+ get_work_area(GTK_WIDGET(nw), &workarea);
+ get_origin_coordinates(stack->location, workarea, &x, &y,
+ &shiftx, &shifty, req.width, req.height);
+
+ theme_move_notification(nw, x, y);
+
+ for (l = stack->windows; l != NULL; l = l->next)
+ {
+ GtkWindow *nw2 = GTK_WINDOW(l->data);
+
+ if (nw2 != nw)
+ {
+ gtk_widget_size_request(GTK_WIDGET(nw2), &req);
+
+ translate_coordinates(stack->location, workarea, &x, &y,
+ &shiftx, &shifty, req.width, req.height,
+ index++);
+ theme_move_notification(nw2, x, y);
+ }
+ }
+
+ if (new_notification)
+ {
+ g_signal_connect_swapped(G_OBJECT(nw), "destroy",
+ G_CALLBACK(notify_stack_remove_window),
+ stack);
+ stack->windows = g_slist_prepend(stack->windows, nw);
+ }
+}
+
+void
+notify_stack_remove_window(NotifyStack *stack,
+ GtkWindow *nw)
+{
+ GdkRectangle workarea;
+ GSList *l, *remove_l = NULL;
+ gint x, y, shiftx = 0, shifty = 0, index = 0;
+
+ get_work_area(GTK_WIDGET(nw), &workarea);
+
+ get_origin_coordinates(stack->location, workarea, &x, &y,
+ &shiftx, &shifty, 0, 0);
+
+ for (l = stack->windows; l != NULL; l = l->next)
+ {
+ GtkWindow *nw2 = GTK_WINDOW(l->data);
+ GtkRequisition req;
+
+ if (nw2 != nw)
+ {
+ gtk_widget_size_request(GTK_WIDGET(nw2), &req);
+
+ translate_coordinates(stack->location, workarea, &x, &y,
+ &shiftx, &shifty, req.width, req.height,
+ index++);
+ theme_move_notification(nw2, x, y);
+ }
+ else
+ {
+ remove_l = l;
+ }
+ }
+
+ if (remove_l != NULL)
+ stack->windows = g_slist_remove_link(stack->windows, remove_l);
+
+ if (GTK_WIDGET_REALIZED(GTK_WIDGET(nw)))
+ gtk_widget_unrealize(GTK_WIDGET(nw));
+}
Added: trunk/notification-daemon/src/stack.h
===================================================================
--- trunk/notification-daemon/src/stack.h 2006-07-30 04:40:40 UTC (rev 2889)
+++ trunk/notification-daemon/src/stack.h 2006-07-30 21:23:40 UTC (rev 2890)
@@ -0,0 +1,52 @@
+/*
+ * stack.h - Notification stack groups.
+ *
+ * Copyright (C) 2006 Christian Hammond <chipx86 at chipx86.com>
+ *
+ * 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, 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 _NOTIFY_STACK_H_
+#define _NOTIFY_STACK_H_
+
+#include <gtk/gtk.h>
+#include "daemon.h"
+
+typedef enum
+{
+ NOTIFY_STACK_LOCATION_UNKNOWN = -1,
+ NOTIFY_STACK_LOCATION_TOP_LEFT,
+ NOTIFY_STACK_LOCATION_TOP_RIGHT,
+ NOTIFY_STACK_LOCATION_BOTTOM_LEFT,
+ NOTIFY_STACK_LOCATION_BOTTOM_RIGHT,
+ NOTIFY_STACK_LOCATION_DEFAULT = NOTIFY_STACK_LOCATION_BOTTOM_RIGHT
+
+} NotifyStackLocation;
+
+typedef struct _NotifyStack NotifyStack;
+
+NotifyStack *notify_stack_new(NotifyDaemon *daemon,
+ GdkScreen *screen,
+ guint monitor,
+ NotifyStackLocation stack_location);
+void notify_stack_destroy(NotifyStack *stack);
+
+void notify_stack_set_location(NotifyStack *stack,
+ NotifyStackLocation location);
+void notify_stack_add_window(NotifyStack *stack, GtkWindow *nw,
+ gboolean new_notification);
+void notify_stack_remove_window(NotifyStack *stack, GtkWindow *nw);
+
+#endif /* _NOTIFY_STACK_H_ */
More information about the galago-commits
mailing list