rpms/notification-daemon/devel notification-daemon-positioning.patch, NONE, 1.1 notification-daemon-svn3009-distfix.patch, NONE, 1.1 notification-daemon.spec, 1.20, 1.21

Colin Walters (walters) fedora-extras-commits at redhat.com
Tue Jun 10 16:17:47 UTC 2008


Author: walters

Update of /cvs/pkgs/rpms/notification-daemon/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv2861

Modified Files:
	notification-daemon.spec 
Added Files:
	notification-daemon-positioning.patch 
	notification-daemon-svn3009-distfix.patch 
Log Message:
* Tue Jun 10 2008 Colin Walters <walters at redhat.com> -0.3.7.90-0.svn3009
- Update to SVN snapshot 3009 so we can apply:
- Add positioning patch
- Add patch to fix the dist
- Drop upstreamed summary patch


notification-daemon-positioning.patch:

--- NEW FILE notification-daemon-positioning.patch ---
Index: src/daemon/daemon.c
===================================================================
--- src/daemon/daemon.c	(revision 3009)
+++ src/daemon/daemon.c	(working copy)
@@ -81,15 +81,19 @@
 	GTimeVal paused_diff;
 	gboolean has_timeout;
 	gboolean paused;
+	gint cached_x;
+	gint cached_y;
 	guint id;
 	GtkWindow *nw;
-
+	Window srcwindow_xid;
 } NotifyTimeout;
 
 struct _NotifyDaemonPrivate
 {
 	guint next_id;
 	guint timeout_source;
+	GHashTable *idle_reposition_notify_ids;
+	GHashTable *monitored_window_hash;
 	GHashTable *notification_hash;
 	gboolean url_clicked_lock;
 	NotifyStack **stacks;
@@ -118,9 +122,14 @@
 static void _close_notification(NotifyDaemon *daemon, guint id,
 								gboolean hide_notification,
 								NotifydClosedReason reason);
+static GdkFilterReturn _notify_x11_filter (GdkXEvent *xevent, 
+			      GdkEvent  *event, 
+			      gpointer   user_data);
 static void _emit_closed_signal(GtkWindow *nw, NotifydClosedReason reason);
 static void _action_invoked_cb(GtkWindow *nw, const char *key);
 static NotifyStackLocation get_stack_location_from_string(const char *slocation);
+static void sync_notification_position(NotifyDaemon *daemon, NotifyTimeout *nt);
+static void monitor_notification_source_windows(NotifyDaemon *daemon, NotifyTimeout *nt, Window source);
 
 G_DEFINE_TYPE(NotifyDaemon, notify_daemon, G_TYPE_OBJECT);
 
@@ -167,6 +176,10 @@
 	daemon->priv->stacks_size = gdk_screen_get_n_monitors(screen);
 	daemon->priv->stacks = g_new0(NotifyStack *, daemon->priv->stacks_size);
 
+	daemon->priv->idle_reposition_notify_ids = g_hash_table_new (NULL, NULL);
+	daemon->priv->monitored_window_hash = g_hash_table_new (NULL, NULL);
+	gdk_window_add_filter (NULL, _notify_x11_filter, daemon);
+
 	for (i = 0; i < daemon->priv->stacks_size; i++)
 	{
 		daemon->priv->stacks[i] = notify_stack_new(daemon, screen,
@@ -184,6 +197,8 @@
 	NotifyDaemon *daemon       = NOTIFY_DAEMON(object);
 	GObjectClass *parent_class = G_OBJECT_CLASS(notify_daemon_parent_class);
 
+	g_hash_table_destroy(daemon->priv->monitored_window_hash);
+	g_hash_table_destroy(daemon->priv->idle_reposition_notify_ids);
 	g_hash_table_destroy(daemon->priv->notification_hash);
 	g_free(daemon->priv);
 
@@ -295,7 +310,99 @@
 						NOTIFYD_CLOSED_EXPIRED);
 }
 
+struct idle_reposition_data
+{
+	NotifyDaemon *daemon;
+	gint id;
+};
+
+static gboolean
+idle_reposition_notification(gpointer datap)
+{
+	struct idle_reposition_data *data=(struct idle_reposition_data*)datap;
+	NotifyDaemon *daemon = data->daemon;
+	NotifyTimeout *nt;
+	gint notify_id;
+
+	notify_id = data->id;
+
+	/* Look up the timeout, if it's completed we don't need to do anything */
+	nt = (NotifyTimeout *)g_hash_table_lookup(daemon->priv->notification_hash, &notify_id);
+	if (!nt)
+		goto out;
+	
+	sync_notification_position(daemon, nt);
+
+	out:
+	g_hash_table_remove(daemon->priv->idle_reposition_notify_ids, GINT_TO_POINTER(notify_id));
+	g_object_unref(daemon);
+	g_free(data);
+	return FALSE;
+}
+
 static void
+_queue_idle_reposition_notification(NotifyDaemon *daemon, gint notify_id)
+{
+	struct idle_reposition_data *data;
+	gpointer orig_key;
+	gpointer value;
+	guint idle_id;
+
+	/* Do we already have an idle update pending? */
+	if (g_hash_table_lookup_extended(daemon->priv->idle_reposition_notify_ids,
+					 GINT_TO_POINTER (notify_id), &orig_key, &value))
+		return;
+
+	data = g_new0(struct idle_reposition_data, 1);
+	g_object_ref (daemon);
+	data->daemon = daemon;
+	data->id = notify_id;
+	/* We do this as a short timeout to avoid repositioning spam */
+	idle_id = g_timeout_add_full (G_PRIORITY_LOW, 50, idle_reposition_notification, data, NULL);
+	g_hash_table_insert (daemon->priv->idle_reposition_notify_ids, 
+			     GINT_TO_POINTER (notify_id), GUINT_TO_POINTER (idle_id));
+}
+
+static GdkFilterReturn 
+_notify_x11_filter (GdkXEvent *xevent, 
+		    GdkEvent  *event, 
+		    gpointer   user_data)
+{
+	NotifyDaemon *daemon = NOTIFY_DAEMON (user_data);
+	XEvent *xev = (XEvent *)xevent;
+	gpointer orig_key;
+	gpointer value;
+	gint notify_id;
+	NotifyTimeout *nt;
+
+	if (xev->xany.type == DestroyNotify)
+	{
+		g_hash_table_remove(daemon->priv->monitored_window_hash, GUINT_TO_POINTER(xev->xany.window));
+		return GDK_FILTER_CONTINUE;
+	}
+
+	if (!g_hash_table_lookup_extended(daemon->priv->monitored_window_hash,
+					 GUINT_TO_POINTER(xev->xany.window), &orig_key, &value))
+		return GDK_FILTER_CONTINUE;
+
+	notify_id = GPOINTER_TO_INT (value);
+	if (xev->xany.type == ConfigureNotify || xev->xany.type == MapNotify)
+	{
+		_queue_idle_reposition_notification(daemon, notify_id);
+	}
+	else if (xev->xany.type == ReparentNotify)
+	{
+		nt = (NotifyTimeout *)g_hash_table_lookup(daemon->priv->notification_hash, &notify_id);
+		if (!nt)
+			return GDK_FILTER_CONTINUE;
+		/* If the window got reparented, we need to start monitoring the new parents */
+		monitor_notification_source_windows(daemon, nt, nt->srcwindow_xid);
+		sync_notification_position(daemon, nt);
+	}
+	return GDK_FILTER_CONTINUE;
+}
+
+static void
 _mouse_entered_cb(GtkWindow *nw, GdkEventCrossing *event, NotifyDaemon *daemon)
 {
 	NotifyTimeout *nt;
@@ -436,7 +543,7 @@
 	}
 }
 
-static guint
+static NotifyTimeout *
 _store_notification(NotifyDaemon *daemon, GtkWindow *nw, int timeout)
 {
 	NotifyDaemonPrivate *priv = daemon->priv;
@@ -460,13 +567,15 @@
 	nt = g_new0(NotifyTimeout, 1);
 	nt->id = id;
 	nt->nw = nw;
+	nt->cached_x = -1;
+	nt->cached_y = -1;
 
 	_calculate_timeout(daemon, nt, timeout);
 
 	g_hash_table_insert(priv->notification_hash,
 						g_memdup(&id, sizeof(guint)), nt);
 
-	return id;
+	return nt;
 }
 
 static gboolean
@@ -634,7 +743,7 @@
 	if (expected_len != tmp_array->len)
 	{
 		g_warning("_notify_daemon_process_icon_data expected image "
-				  "data to be of length %i but got a length of %i",
+				  "data to be of length %" G_GSIZE_FORMAT " but got a length of %u",
 				  expected_len, tmp_array->len);
 		return FALSE;
 	}
@@ -822,6 +931,101 @@
 	return FALSE;
 }
 
+static Window
+get_window_parent (Display *display, Window window, Window *root)
+{
+	Window parent;
+	Window *children = NULL;
+	guint nchildren;
+	gboolean result;
+
+	gdk_error_trap_push ();
+	result = XQueryTree (display, window, root, &parent, &children, &nchildren);
+	if (gdk_error_trap_pop () || !result)
+		return None;
+
+	if (children)
+		XFree (children);
+	return parent;
+}
+
+/* Recurse over X Window and parents, up to root, and start watching them
+ * for position changes
+ */
+static void
+monitor_notification_source_windows(NotifyDaemon *daemon, NotifyTimeout *nt, Window source)
+{
+	Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+	Window root = None;
+	Window parent;
+
+	/* Store the window in the timeout */
+	g_assert(nt != NULL);
+	nt->srcwindow_xid = source;
+
+	parent = get_window_parent(display, source, &root);
+	while ((parent != None) && root != parent) {
+		XSelectInput(display, parent, StructureNotifyMask);
+		g_hash_table_insert(daemon->priv->monitored_window_hash, 
+				    GUINT_TO_POINTER(parent), GINT_TO_POINTER(nt->id));
+
+		parent = get_window_parent(display, parent, &root);
+	}
+}
+
+/* Use a source X Window ID to reposition a notification */
+static void
+sync_notification_position(NotifyDaemon *daemon, NotifyTimeout *nt)
+{
+	Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+	Window source = nt->srcwindow_xid;
+	GtkWindow *nw = nt->nw;
+	Status result;
+	Window root;
+	Window child;
+        int x, y;
+	unsigned int width, height;
+        unsigned int border_width, depth;
+
+
+	gdk_error_trap_push ();
+	/* Get the root for this window */
+	result = XGetGeometry (display, source,
+		 	       &root, &x, &y, &width, &height, &border_width, &depth);
+	if (gdk_error_trap_pop () || !result)
+	{
+		return;
+	}
+	/* Now calculate the offset coordinates for the source window from the root */
+	gdk_error_trap_push ();
+        result = XTranslateCoordinates (display,
+					source,
+					root,
+					0, 0, &x, &y,
+					&child);
+	if (gdk_error_trap_pop () || !result)
+	{
+		return;
+	}
+
+	x += (width/2);
+	y += (height/2);
+
+	if (x == nt->cached_x && y == nt->cached_y)
+		return;
+	nt->cached_x = x;
+	nt->cached_y = y;
+
+	fprintf(stderr, "repositioning at %i %i\n", x, y);	
+	theme_set_notification_arrow(nw, TRUE, x, y);
+	theme_move_notification(nw, x, y);
+	/* We need to do a full draw as the default theme recalculates
+	 * its position in the draw handler and moves the window (which seems fairly
+	 * broken), so just calling set_arrow/move isn't enough to cause its position to
+	 * be calculated. */
+	gtk_widget_queue_draw(GTK_WIDGET(nw));
+}
+
 GQuark
 notify_daemon_error_quark(void)
 {
@@ -852,6 +1056,7 @@
 	gboolean new_notification = FALSE;
 	gint x = 0;
 	gint y = 0;
+	Window window_xid = None;
 	guint return_id;
 	gchar *sender;
 	gchar *sound_file = NULL;
@@ -897,8 +1102,13 @@
 	 *XXX This needs to handle file URIs and all that.
 	 */
 
+
+	if ((data = (GValue *)g_hash_table_lookup(hints, "window-xid")) != NULL)
+	{
+		window_xid = (Window) g_value_get_uint(data);
+	}
 	/* deal with x, and y hints */
-	if ((data = (GValue *)g_hash_table_lookup(hints, "x")) != NULL)
+	else if ((data = (GValue *)g_hash_table_lookup(hints, "x")) != NULL)
 	{
 		x = g_value_get_int(data);
 
@@ -1044,8 +1254,15 @@
 		}
 	}
 
-	if (use_pos_data)
+
+	if (window_xid != None)
 	{
+		/* Do nothing here if we were passed an XID; we'll call 
+		 * sync_notification_position later.
+		 */
+	}
+	else if (use_pos_data)
+	{
 		/*
 		 * Typically, the theme engine will set its own position based on
 		 * the arrow X, Y hints. However, in case, move the notification to
@@ -1070,6 +1287,24 @@
 		notify_stack_add_window(priv->stacks[monitor], nw, new_notification);
 	}
 
+	if (id == 0)
+	{
+		nt = _store_notification(daemon, nw, timeout);
+		return_id = nt->id;
+	}
+	else
+		return_id = id;
+
+	/* If we have a source Window XID, start monitoring the tree
+	 * for changes, and reposition the window based on the source
+	 * window.  We need to do this after return_id is calculated.
+	 */
+	if (window_xid != None) 
+	{
+		monitor_notification_source_windows(daemon, nt, window_xid);
+		sync_notification_position(daemon, nt);
+	}
+
 	if (!screensaver_active(GTK_WIDGET(nw)) &&
 		!fullscreen_window_exists(GTK_WIDGET(nw)))
 	{
@@ -1080,8 +1315,6 @@
 
 	g_free(sound_file);
 
-	return_id = (id == 0 ? _store_notification(daemon, nw, timeout) : id);
-
 #if CHECK_DBUS_VERSION(0, 60)
 	sender = dbus_g_method_get_sender(context);
 #else
Index: src/themes/standard/theme.c
===================================================================
--- src/themes/standard/theme.c	(revision 3009)
+++ src/themes/standard/theme.c	(working copy)
@@ -214,6 +214,7 @@
 	int width;
 	int height;
 	int y;
+	int target_x, target_y;
 	int norm_point_x;
 	int norm_point_y;
 	GtkArrowType arrow_type;
@@ -259,14 +260,10 @@
 			}
 			else
 			{
-				if (norm_point_x - arrow_side2_width + width >=
-					monitor_geometry.width)
+				int right_x = norm_point_x - arrow_side1_width + width;
+				if (right_x >= monitor_geometry.width)
 				{
-					arrow_offset =
-						width - arrow_side1_width - arrow_side2_width -
-						monitor_geometry.width -
-						MAX(norm_point_x + arrow_side1_width,
-							monitor_geometry.width - DEFAULT_ARROW_OFFSET);
+					arrow_offset = right_x - monitor_geometry.width;
 				}
 				else
 				{
@@ -384,10 +381,9 @@
 			g_assert(i == windata->num_border_points);
 			g_assert(windata->point_x - arrow_offset - arrow_side1_width >= 0);
 #endif
-			gtk_window_move(GTK_WINDOW(windata->win),
-							windata->point_x - arrow_offset -
-							arrow_side1_width,
-							y);
+			target_x = windata->point_x - arrow_offset - arrow_side1_width;
+			target_y = y;
+			gtk_window_move(GTK_WINDOW(windata->win), target_x, target_y);
 
 			break;
 

notification-daemon-svn3009-distfix.patch:

--- NEW FILE notification-daemon-svn3009-distfix.patch ---
Index: src/capplet/Makefile.am
===================================================================
--- src/capplet/Makefile.am	(revision 3009)
+++ src/capplet/Makefile.am	(working copy)
@@ -20,4 +20,4 @@
 	-DNOTIFICATION_GLADEDIR=\"$(datadir)/notification-daemon\"
 
 CLEANFILES = $(desktop_DATA)
-EXTRA_DIST = $(glade_DATA) $(pixmap_DATA)
+EXTRA_DIST = $(glade_DATA) $(pixmap_DATA) $(desktop_in_files)


Index: notification-daemon.spec
===================================================================
RCS file: /cvs/pkgs/rpms/notification-daemon/devel/notification-daemon.spec,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- notification-daemon.spec	7 Apr 2008 03:33:57 -0000	1.20
+++ notification-daemon.spec	10 Jun 2008 16:17:01 -0000	1.21
@@ -6,8 +6,8 @@
 
 Summary: Notification Daemon
 Name: notification-daemon
-Version: 0.3.7
-Release: 9%{?dist}
+Version: 0.3.7.90
+Release: 0.svn3009%{?dist}
 URL: http://www.galago-project.org/specs/notification/
 License: GPLv2+
 Group: System Environment/Libraries
@@ -31,10 +31,11 @@
 
 Obsoletes: notify-daemon
 
-Source0: http://www.galago-project.org/files/releases/source/notification-daemon/%{name}-%{version}.tar.bz2
+Source0: http://www.galago-project.org/files/releases/source/notification-daemon/%{name}-%{version}.tar.gz
 Patch0: notification-daemon-0.3.5-remove-libsexy.patch
-Patch1: notification-daemon-0.3.7-summary-markup.patch
 Patch2: notification-daemon-clipping.patch
+Patch3: notification-daemon-svn3009-distfix.patch
+Patch4: notification-daemon-positioning.patch
 
 %description
 notification-daemon is the server implementation of the freedesktop.org desktop
@@ -43,8 +44,9 @@
 %prep
 %setup -q
 %patch0 -p1 -b .remove-libsexy
-%patch1 -p1 -b .summary-markup
 %patch2 -p1 -b .clipping
+%patch3 -p0 -b .svn3009-distfix
+%patch4 -p0 -b .positioning
 
 %build
 autoreconf
@@ -97,6 +99,12 @@
 %config %{_sysconfdir}/gconf/schemas/notification-daemon.schemas
 
 %changelog
+* Tue Jun 10 2008 Colin Walters <walters at redhat.com> -0.3.7.90-0.svn3009
+- Update to SVN snapshot 3009 so we can apply:
+- Add positioning patch
+- Add patch to fix the dist
+- Drop upstreamed summary patch
+
 * Sun Apr  6 2008 Jon McCann <jmccann at redhat.com> - 0.3.7-9
 - Don't clip text in message bubbles (#441099)
 




More information about the fedora-extras-commits mailing list