Hard code freeze break request for nautilus



Hi,

I'd like to request permission to break hard code freeze for the
attached nautilus patch.  It has been approved by Alex, pending
permission from the release team.

The problem this patch fixes:
if nautilus is launched without startup-notification (some examples of
where this happens is using the "Desktop" entry in the "Places" panel
menu or using bookmarks made in the filechooser; see bug 166242,
comment 2), those windows have not been getting focus and have been
stacked below the previous focus window.  Similarly, if the window was
already open somewhere then metacity would get a request to show the
existing window, but the request would appear to be very old and thus
metacity wouldn't want to interrupt the users' work that it thought
had occurred in the meantime by actually showing the window.

The basic idea:
gtk+ provides a default hint to the window manager about when a given
window was launched.  This default is used by nautilus when
startup-notification doesn't provide the exact launch time, but this
default sucks for apps like nautilus that forward an
"open-a-window-for-me" request to a previous instance.  This patch
provides a pretty good approximation to launch time in those cases to
use instead of the gtk+ default.

Severity, trade-offs, etc.:
This is basically a way to work around any regressions relative to
Gnome 2.8 that bug 166722 is causing so that we can punt that bug
until 2.12 (because fixing 166722, one of the showstoppers on Luis'
list, would be far more involved).  The majority of the patch is a
verbatim copy&paste of a single function from elsewhere in nautilus
that has been used for months and thus should be perfectly safe.  The
remainder of the patch is pretty short and I believe safe and
straightforward.  It does introduce the possibility of nautilus
windows stealing focus when they shouldn't (but only if the user is
really fast and startup is really slow), but I don't think any better
could be done when startup-notification isn't used and it makes the
default behavior much saner.

Thanks,
Elijah
Index: src/nautilus-application.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-application.c,v
retrieving revision 1.231
diff -p -u -r1.231 nautilus-application.c
--- src/nautilus-application.c	22 Feb 2005 08:46:38 -0000	1.231
+++ src/nautilus-application.c	28 Feb 2005 19:47:26 -0000
@@ -1034,8 +1034,14 @@ end_startup_notification (GtkWidget  *wi
 					   gdk_screen_get_number (screen),
 					   startup_id);
 
-	sn_launchee_context_setup_window (context,
-					  GDK_WINDOW_XWINDOW (widget->window));
+	/* Handle the setup for the window if the startup_id is valid;
+	 * I don't think it can hurt to do this even if it was
+	 * invalid, but why do the extra work...
+	 */
+	if (strncmp (sn_launchee_context_get_startup_id (context), "_TIME", 5) != 0) {
+		sn_launchee_context_setup_window (context,
+						  GDK_WINDOW_XWINDOW (widget->window));
+	}
 
 	/* Now, set the _NET_WM_USER_TIME for the new window to the timestamp
 	 * that caused the window to be launched.
@@ -1044,14 +1050,6 @@ end_startup_notification (GtkWidget  *wi
 		gulong startup_id_timestamp;
 		startup_id_timestamp = sn_launchee_context_get_timestamp (context);
 		gdk_x11_window_set_user_time (widget->window, startup_id_timestamp);
-	} else {
-		/* Comment this out for now, as it warns way to often.
-		 * like when launching nautilus from the terminal.
-		 
-		g_warning ("Launched by a non-compliant or obsolete startup "
-			   "notification launcher.  Focus-stealing-prevention "
-			   "may fail.\n");
-		*/
 	}
   
 	sn_launchee_context_complete (context);
Index: src/nautilus-main.c
===================================================================
RCS file: /cvs/gnome/nautilus/src/nautilus-main.c,v
retrieving revision 1.144
diff -p -u -r1.144 nautilus-main.c
--- src/nautilus-main.c	14 Feb 2005 10:59:23 -0000	1.144
+++ src/nautilus-main.c	28 Feb 2005 19:47:26 -0000
@@ -54,6 +54,7 @@
 #include <libxml/parser.h>
 #include <popt.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
 /* Keeps track of everyone who wants the main event loop kept active */
@@ -188,6 +189,59 @@ register_icons (void)
 	
 }
 
+/* Copied from libnautilus/nautilus-program-choosing.c; In this case,
+ * though, it's really needed because we have no real alternative when
+ * no DESKTOP_STARTUP_ID (with its accompanying timestamp) is
+ * provided...
+ */
+static Time
+slowly_and_stupidly_obtain_timestamp (Display *xdisplay)
+{
+	Window xwindow;
+	XEvent event;
+	
+	{
+		XSetWindowAttributes attrs;
+		Atom atom_name;
+		Atom atom_type;
+		char* name;
+		
+		attrs.override_redirect = True;
+		attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
+		
+		xwindow =
+			XCreateWindow (xdisplay,
+				       RootWindow (xdisplay, 0),
+				       -100, -100, 1, 1,
+				       0,
+				       CopyFromParent,
+				       CopyFromParent,
+				       CopyFromParent,
+				       CWOverrideRedirect | CWEventMask,
+				       &attrs);
+		
+		atom_name = XInternAtom (xdisplay, "WM_NAME", TRUE);
+		g_assert (atom_name != None);
+		atom_type = XInternAtom (xdisplay, "STRING", TRUE);
+		g_assert (atom_type != None);
+		
+		name = "Fake Window";
+		XChangeProperty (xdisplay, 
+				 xwindow, atom_name,
+				 atom_type,
+				 8, PropModeReplace, name, strlen (name));
+	}
+	
+	XWindowEvent (xdisplay,
+		      xwindow,
+		      PropertyChangeMask,
+		      &event);
+	
+	XDestroyWindow(xdisplay, xwindow);
+	
+	return event.xproperty.time;
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -276,6 +330,15 @@ main (int argc, char *argv[])
 				      GNOME_PARAM_POPT_TABLE, options,
 				      GNOME_PARAM_HUMAN_READABLE_NAME, _("Nautilus"),
 				      NULL);
+
+	/* Do this here so that gdk_display is initialized */
+	if (startup_id_copy == NULL) {
+		/* Create a fake one containing a timestamp that we can use */
+		Time timestamp;
+		timestamp = slowly_and_stupidly_obtain_timestamp (gdk_display);
+		startup_id_copy = g_strdup_printf ("_TIME%lu",
+						   timestamp);
+	}
 
 	register_icons ();
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]