From f0eebf3f41f35c38dfff4c7155f5e5d67c87f9b6 Mon Sep 17 00:00:00 2001 From: Christopher Aillon Date: Sep 25 2007 03:36:23 +0000 Subject: - Startup notification support --- diff --git a/firefox-2.0-startup-notify.patch b/firefox-2.0-startup-notify.patch new file mode 100644 index 0000000..9598113 --- /dev/null +++ b/firefox-2.0-startup-notify.patch @@ -0,0 +1,1121 @@ +https://bugzilla.mozilla.org/show_bug.cgi?id=223492 + +--- config/autoconf.mk.in 2006-09-14 14:07:03.000000000 -0400 ++++ config/autoconf.mk.in 2007-07-03 18:01:36.000000000 -0400 +@@ -223,6 +223,10 @@ + MOZ_GNOMEUI_CFLAGS = @MOZ_GNOMEUI_CFLAGS@ + MOZ_GNOMEUI_LIBS = @MOZ_GNOMEUI_LIBS@ + ++MOZ_ENABLE_STARTUP_NOTIFICATION = @MOZ_ENABLE_STARTUP_NOTIFICATION@ ++MOZ_STARTUP_NOTIFICATION_CFLAGS = @MOZ_STARTUP_NOTIFICATION_CFLAGS@ ++MOZ_STARTUP_NOTIFICATION_LIBS = @MOZ_STARTUP_NOTIFICATION_LIBS@ ++ + MOZ_GNOMEVFS_CFLAGS = @MOZ_GNOMEVFS_CFLAGS@ + MOZ_GNOMEVFS_LIBS = @MOZ_GNOMEVFS_LIBS@ + +--- toolkit/components/remote/nsGTKRemoteService.cpp 2006-01-05 22:19:20.000000000 -0500 ++++ toolkit/components/remote/nsGTKRemoteService.cpp 2007-07-05 17:34:41.000000000 -0400 +@@ -50,7 +50,9 @@ + + #include "nsIBaseWindow.h" + #include "nsIDocShell.h" ++#include "nsIDocument.h" + #include "nsIDOMWindow.h" ++#include "nsPIDOMWindow.h" + #include "nsIGenericFactory.h" + #include "nsILocalFile.h" + #include "nsIObserverService.h" +@@ -58,6 +60,8 @@ + #include "nsIServiceManager.h" + #include "nsIWeakReference.h" + #include "nsIWidget.h" ++#include "nsIAppShellService.h" ++#include "nsAppShellCID.h" + + #include "nsCOMPtr.h" + #include "nsString.h" +@@ -65,6 +69,10 @@ + #include "prenv.h" + #include "nsCRT.h" + ++#ifdef MOZ_WIDGET_GTK2 ++#include "nsGTKToolkit.h" ++#endif ++ + #ifdef MOZ_XUL_APP + #include "nsICommandLineRunner.h" + #include "nsXULAppAPI.h" +@@ -155,20 +163,46 @@ + return PL_DHASH_NEXT; + } + ++static nsIWidget* GetMainWidget(nsIDOMWindow* aWindow) ++{ ++ // get the native window for this instance ++ nsCOMPtr window(do_QueryInterface(aWindow)); ++ NS_ENSURE_TRUE(window, nsnull); ++ nsCOMPtr doc(do_QueryInterface(window->GetExtantDocument())); ++ NS_ENSURE_TRUE(doc, nsnull); ++ nsCOMPtr container = doc->GetContainer(); ++ nsCOMPtr baseWindow(do_QueryInterface(container)); ++ NS_ENSURE_TRUE(baseWindow, nsnull); ++ ++ nsCOMPtr mainWidget; ++ baseWindow->GetMainWidget(getter_AddRefs(mainWidget)); ++ return mainWidget; ++} ++ ++static nsGTKToolkit* GetGTKToolkit() ++{ ++ nsCOMPtr svc = do_GetService(NS_APPSHELLSERVICE_CONTRACTID); ++ if (!svc) ++ return nsnull; ++ nsCOMPtr window; ++ svc->GetHiddenDOMWindow(getter_AddRefs(window)); ++ if (!window) ++ return nsnull; ++ nsIWidget* widget = GetMainWidget(window); ++ if (!widget) ++ return nsnull; ++ nsIToolkit* toolkit = widget->GetToolkit(); ++ if (!toolkit) ++ return nsnull; ++ return NS_STATIC_CAST(nsGTKToolkit*, toolkit); ++} ++ ++ + NS_IMETHODIMP + nsGTKRemoteService::RegisterWindow(nsIDOMWindow* aWindow) + { + // get the native window for this instance +- nsCOMPtr scriptObject +- (do_QueryInterface(aWindow)); +- NS_ENSURE_TRUE(scriptObject, NS_ERROR_FAILURE); +- +- nsCOMPtr baseWindow +- (do_QueryInterface(scriptObject->GetDocShell())); +- NS_ENSURE_TRUE(baseWindow, NS_ERROR_FAILURE); +- +- nsCOMPtr mainWidget; +- baseWindow->GetMainWidget(getter_AddRefs(mainWidget)); ++ nsIWidget* mainWidget = GetMainWidget(aWindow); + NS_ENSURE_TRUE(mainWidget, NS_ERROR_FAILURE); + + // walk up the widget tree and find the toplevel window in the +@@ -201,7 +235,6 @@ + + return NS_OK; + } +- + NS_IMETHODIMP + nsGTKRemoteService::Shutdown() + { +@@ -260,7 +293,7 @@ + + #ifndef MOZ_XUL_APP + const char* +-nsGTKRemoteService::HandleCommand(char* aCommand, nsIDOMWindow* aWindow) ++nsGTKRemoteService::HandleCommand(char* aCommand, nsIDOMWindow* aWindow, PRUint32 aTimestamp) + { + nsresult rv; + +@@ -283,8 +316,60 @@ + } + + #else //MOZ_XUL_APP ++ ++// Set desktop startup ID to the passed ID, if there is one, so that any created ++// windows get created with the right window manager metadata, and any windows ++// that get new tabs and are activated also get the right WM metadata. ++// If there is no desktop startup ID, then use the X event's timestamp ++// for _NET_ACTIVE_WINDOW when the window gets focused or shown. ++static void ++SetDesktopStartupIDOrTimestamp(const nsACString& aDesktopStartupID, ++ PRUint32 aTimestamp) { ++#ifdef MOZ_WIDGET_GTK2 ++ nsGTKToolkit* toolkit = GetGTKToolkit(); ++ if (!toolkit) ++ return; ++ if (!aDesktopStartupID.IsEmpty()) { ++ toolkit->SetDesktopStartupID(aDesktopStartupID); ++ } else { ++ toolkit->SetFocusTimestamp(aTimestamp); ++ } ++#endif ++} ++ ++static PRBool ++FindExtensionParameterInCommand(const char* aParameterName, ++ const nsACString& aCommand, ++ char aSeparator, ++ nsACString* aValue) ++{ ++ nsCAutoString searchFor; ++ searchFor.Append(aSeparator); ++ searchFor.Append(aParameterName); ++ searchFor.Append('='); ++ ++ nsACString::const_iterator start, end; ++ aCommand.BeginReading(start); ++ aCommand.EndReading(end); ++ if (!FindInReadable(searchFor, start, end)) ++ return PR_FALSE; ++ ++ nsACString::const_iterator charStart, charEnd; ++ charStart = end; ++ aCommand.EndReading(charEnd); ++ nsACString::const_iterator idStart = charStart, idEnd; ++ if (FindCharInReadable(aSeparator, charStart, charEnd)) { ++ idEnd = charStart; ++ } else { ++ idEnd = charEnd; ++ } ++ *aValue = nsDependentCSubstring(idStart, idEnd); ++ return PR_TRUE; ++} ++ + const char* +-nsGTKRemoteService::HandleCommand(char* aCommand, nsIDOMWindow* aWindow) ++nsGTKRemoteService::HandleCommand(char* aCommand, nsIDOMWindow* aWindow, ++ PRUint32 aTimestamp) + { + nsresult rv; + +@@ -314,6 +399,12 @@ + #endif + + if (!command.EqualsLiteral("ping")) { ++ nsCAutoString desktopStartupID; ++ nsDependentCString cmd(aCommand); ++ FindExtensionParameterInCommand("DESKTOP_STARTUP_ID", ++ cmd, '\n', ++ &desktopStartupID); ++ + char* argv[3] = {"dummyappname", "-remote", aCommand}; + rv = cmdline->Init(3, argv, nsnull, nsICommandLine::STATE_REMOTE_EXPLICIT); + if (NS_FAILED(rv)) +@@ -322,6 +413,8 @@ + if (aWindow) + cmdline->SetWindowContext(aWindow); + ++ SetDesktopStartupIDOrTimestamp(desktopStartupID, aTimestamp); ++ + rv = cmdline->Run(); + if (NS_ERROR_ABORT == rv) + return "500 command not parseable"; +@@ -333,7 +426,8 @@ + } + + const char* +-nsGTKRemoteService::HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow) ++nsGTKRemoteService::HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow, ++ PRUint32 aTimestamp) + { + nsresult rv; + +@@ -364,6 +458,8 @@ + if (NS_FAILED(rv)) + return "509 internal error"; + ++ nsCAutoString desktopStartupID; ++ + char **argv = (char**) malloc(sizeof(char*) * argc); + if (!argv) return "509 internal error"; + +@@ -372,6 +468,12 @@ + for (int i = 0; i < argc; ++i) { + argv[i] = aBuffer + TO_LITTLE_ENDIAN32(offset[i]); + ++ if (i == 0) { ++ nsDependentCString cmd(argv[0]); ++ FindExtensionParameterInCommand("DESKTOP_STARTUP_ID", ++ cmd, ' ', ++ &desktopStartupID); ++ } + #ifdef DEBUG_bsmedberg + printf(" argv[%i]:\t%s\n", i, argv[i]); + #endif +@@ -386,7 +488,10 @@ + if (aWindow) + cmdline->SetWindowContext(aWindow); + ++ SetDesktopStartupIDOrTimestamp(desktopStartupID, aTimestamp); ++ + rv = cmdline->Run(); ++ + if (NS_ERROR_ABORT == rv) + return "500 command not parseable"; + +@@ -486,7 +591,7 @@ + return FALSE; + + // cool, we got the property data. +- const char *response = HandleCommand(data, window); ++ const char *response = HandleCommand(data, window, pevent->time); + + // put the property onto the window as the response + XChangeProperty (GDK_DISPLAY(), GDK_WINDOW_XWINDOW(pevent->window), +@@ -531,7 +636,7 @@ + return FALSE; + + // cool, we got the property data. +- const char *response = HandleCommandLine(data, window); ++ const char *response = HandleCommandLine(data, window, pevent->time); + + // put the property onto the window as the response + XChangeProperty (GDK_DISPLAY(), GDK_WINDOW_XWINDOW(pevent->window), +--- toolkit/components/remote/nsGTKRemoteService.h 2005-04-04 19:11:42.000000000 -0400 ++++ toolkit/components/remote/nsGTKRemoteService.h 2007-07-03 18:01:36.000000000 -0400 +@@ -80,10 +80,12 @@ + nsIWeakReference* aData, + void* aClosure); + +- static const char* HandleCommand(char* aCommand, nsIDOMWindow* aWindow); ++ static const char* HandleCommand(char* aCommand, nsIDOMWindow* aWindow, ++ PRUint32 aTimestamp); + + #ifdef MOZ_XUL_APP +- static const char* HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow); ++ static const char* HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow, ++ PRUint32 aTimestamp); + #endif + + static gboolean HandlePropertyChange(GtkWidget *widget, +--- toolkit/components/remote/Makefile.in 2005-04-08 00:59:36.000000000 -0400 ++++ toolkit/components/remote/Makefile.in 2007-07-05 17:45:55.000000000 -0400 +@@ -56,7 +56,9 @@ + string \ + appcomps \ + toolkitcomps \ +- appcomps \ ++ appshell \ ++ layout \ ++ content \ + xulapp \ + widget \ + gfx \ +--- toolkit/library/Makefile.in 2007-04-03 10:32:27.000000000 -0400 ++++ toolkit/library/Makefile.in 2007-07-03 18:01:36.000000000 -0400 +@@ -357,6 +357,10 @@ + EXTRA_DSO_LDOPTS += $(MOZ_XPRINT_LDFLAGS) + endif + ++ifdef MOZ_ENABLE_STARTUP_NOTIFICATION ++EXTRA_DSO_LDOPTS += $(MOZ_STARTUP_NOTIFICATION_LIBS) ++endif ++ + ifdef MOZ_ENABLE_PANGO + EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS) + endif +--- toolkit/xre/nsAppRunner.cpp 2007-04-30 13:26:58.000000000 -0400 ++++ toolkit/xre/nsAppRunner.cpp 2007-07-05 17:48:51.000000000 -0400 +@@ -72,6 +72,7 @@ + #include "nsIComponentRegistrar.h" + #include "nsIContentHandler.h" + #include "nsIDialogParamBlock.h" ++#include "nsIDocument.h" + #include "nsIDOMWindow.h" + #include "nsIEventQueueService.h" + #include "nsIExtensionManager.h" +@@ -99,6 +100,11 @@ + #ifdef XP_WIN + #include "nsIWinAppHelper.h" + #endif ++#include "nsPIDOMWindow.h" ++#include "nsIBaseWindow.h" ++#include "nsIWidget.h" ++#include "nsIDocShell.h" ++#include "nsAppShellCID.h" + + #include "nsCRT.h" + #include "nsCOMPtr.h" +@@ -262,6 +268,9 @@ + #if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2) + #include + #endif //MOZ_WIDGET_GTK || MOZ_WIDGET_GTK2 ++#if defined(MOZ_WIDGET_GTK2) ++#include "nsGTKToolkit.h" ++#endif + + #if defined(MOZ_WIDGET_QT) + #include +@@ -1105,7 +1114,7 @@ + // use int here instead of a PR type since it will be returned + // from main - just to keep types consistent + static int +-HandleRemoteArgument(const char* remote) ++HandleRemoteArgument(const char* remote, const char* aDesktopStartupID) + { + nsresult rv; + ArgResult ar; +@@ -1146,7 +1155,7 @@ + nsXPIDLCString response; + PRBool success = PR_FALSE; + rv = client.SendCommand(program.get(), username, profile, remote, +- getter_Copies(response), &success); ++ aDesktopStartupID, getter_Copies(response), &success); + // did the command fail? + if (NS_FAILED(rv)) { + PR_fprintf(PR_STDERR, "Error: Failed to send command: %s\n", +@@ -1163,7 +1172,7 @@ + } + + static PRBool +-RemoteCommandLine() ++RemoteCommandLine(const char* aDesktopStartupID) + { + nsresult rv; + ArgResult ar; +@@ -1195,7 +1204,7 @@ + nsXPIDLCString response; + PRBool success = PR_FALSE; + rv = client.SendCommandLine(program.get(), username, nsnull, +- gArgc, gArgv, ++ gArgc, gArgv, aDesktopStartupID, + getter_Copies(response), &success); + // did the command fail? + if (NS_FAILED(rv) || !success) +@@ -2059,6 +2068,53 @@ + #ifdef MOZ_WIDGET_GTK2 + #include "prlink.h" + typedef void (*_g_set_application_name_fn)(const gchar *application_name); ++typedef void (*_gtk_window_set_auto_startup_notification_fn)(gboolean setting); ++ ++static PRFuncPtr FindFunction(const char* aName) ++{ ++ PRLibrary *lib = nsnull; ++ PRFuncPtr result = PR_FindFunctionSymbolAndLibrary(aName, &lib); ++ // Since the library was already loaded, we can safely unload it here. ++ if (lib) { ++ PR_UnloadLibrary(lib); ++ } ++ return result; ++} ++ ++static nsIWidget* GetMainWidget(nsIDOMWindow* aWindow) ++{ ++ // get the native window for this instance ++ nsCOMPtr window(do_QueryInterface(aWindow)); ++ NS_ENSURE_TRUE(window, nsnull); ++ nsCOMPtr doc(do_QueryInterface(window->GetExtantDocument())); ++ NS_ENSURE_TRUE(doc, nsnull); ++ nsCOMPtr container = doc->GetContainer(); ++ nsCOMPtr baseWindow(do_QueryInterface(container)); ++ NS_ENSURE_TRUE(baseWindow, nsnull); ++ ++ nsCOMPtr mainWidget; ++ baseWindow->GetMainWidget(getter_AddRefs(mainWidget)); ++ return mainWidget; ++} ++ ++static nsGTKToolkit* GetGTKToolkit() ++{ ++ nsCOMPtr svc = do_GetService(NS_APPSHELLSERVICE_CONTRACTID); ++ if (!svc) ++ return nsnull; ++ nsCOMPtr window; ++ svc->GetHiddenDOMWindow(getter_AddRefs(window)); ++ if (!window) ++ return nsnull; ++ nsIWidget* widget = GetMainWidget(window); ++ if (!widget) ++ return nsnull; ++ nsIToolkit* toolkit = widget->GetToolkit(); ++ if (!toolkit) ++ return nsnull; ++ return NS_STATIC_CAST(nsGTKToolkit*, toolkit); ++} ++ + #endif + + int +@@ -2235,6 +2291,16 @@ + if (CheckArg("install")) + gdk_rgb_set_install(TRUE); + ++#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2) || defined(MOZ_ENABLE_XREMOTE) ++ // Stash DESKTOP_STARTUP_ID in malloc'ed memory becaus gtk_init will clear it. ++#define HAVE_DESKTOP_STARTUP_ID ++ const char* desktopStartupIDEnv = PR_GetEnv("DESKTOP_STARTUP_ID"); ++ nsCAutoString desktopStartupID; ++ if (desktopStartupIDEnv) { ++ desktopStartupID.Assign(desktopStartupIDEnv); ++ } ++#endif ++ + // Initialize GTK+1/2 here for splash + #if defined(MOZ_WIDGET_GTK) + gtk_set_locale(); +@@ -2243,15 +2309,15 @@ + + #if defined(MOZ_WIDGET_GTK2) + // g_set_application_name () is only defined in glib2.2 and higher. +- PRLibrary *glib2 = nsnull; +- _g_set_application_name_fn _g_set_application_name = +- (_g_set_application_name_fn)PR_FindFunctionSymbolAndLibrary("g_set_application_name", &glib2); ++ _g_set_application_name_fn _g_set_application_name = ++ (_g_set_application_name_fn)FindFunction("g_set_application_name"); + if (_g_set_application_name) { + _g_set_application_name(gAppData->name); + } +- if (glib2) { +- PR_UnloadLibrary(glib2); +- } ++ _gtk_window_set_auto_startup_notification_fn _gtk_window_set_auto_startup_notification = ++ (_gtk_window_set_auto_startup_notification_fn)FindFunction("gtk_window_set_auto_startup_notification"); ++ if (_gtk_window_set_auto_startup_notification) ++ _gtk_window_set_auto_startup_notification(PR_FALSE); + #endif + + gtk_widget_set_default_visual(gdk_rgb_get_visual()); +@@ -2315,13 +2381,15 @@ + PR_fprintf(PR_STDERR, "Error: -remote requires an argument\n"); + return 1; + } ++ const char* desktopStartupIDPtr = ++ desktopStartupID.IsEmpty() ? nsnull : desktopStartupID.get(); + if (ar) { +- return HandleRemoteArgument(xremotearg); ++ return HandleRemoteArgument(xremotearg, desktopStartupIDPtr); + } + + if (!PR_GetEnv("MOZ_NO_REMOTE")) { + // Try to remote the entire command line. If this fails, start up normally. +- if (RemoteCommandLine()) ++ if (RemoteCommandLine(desktopStartupIDPtr)) + return 0; + } + #endif +@@ -2533,6 +2601,13 @@ + NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow"); + NS_ENSURE_SUCCESS(rv, 1); + ++#if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2) ++ nsRefPtr toolkit = GetGTKToolkit(); ++ if (toolkit && !desktopStartupID.IsEmpty()) { ++ toolkit->SetDesktopStartupID(desktopStartupID); ++ } ++#endif ++ + // Extension Compatibility Checking and Startup + if (gAppData->flags & NS_XRE_ENABLE_EXTENSION_MANAGER) { + nsCOMPtr em(do_GetService("@mozilla.org/extensions/manager;1")); +@@ -2713,6 +2788,21 @@ + } + #endif + ++#if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_TOOLKIT_GTK2) ++ nsGTKToolkit* toolkit = GetGTKToolkit(); ++ if (toolkit) { ++ nsCAutoString currentDesktopStartupID; ++ toolkit->GetDesktopStartupID(¤tDesktopStartupID); ++ if (!currentDesktopStartupID.IsEmpty()) { ++ nsCAutoString desktopStartupEnv; ++ desktopStartupEnv.AssignLiteral("DESKTOP_STARTUP_ID="); ++ desktopStartupEnv.Append(currentDesktopStartupID); ++ // Leak it with extreme prejudice! ++ PR_SetEnv(ToNewCString(desktopStartupEnv)); ++ } ++ } ++#endif ++ + rv = LaunchChild(nativeApp, appInitiatedRestart, upgraded ? -1 : 0); + return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1; + } +--- toolkit/xre/Makefile.in 2007-02-06 02:13:20.000000000 -0500 ++++ toolkit/xre/Makefile.in 2007-07-03 18:01:36.000000000 -0400 +@@ -69,6 +69,7 @@ + shellservice \ + string \ + uriloader \ ++ layout \ + widget \ + windowwatcher \ + xpcom \ +--- configure.in 2007-04-03 11:40:02.000000000 -0400 ++++ configure.in 2007-07-03 18:01:36.000000000 -0400 +@@ -125,6 +125,7 @@ + GNOMEUI_VERSION=2.2.0 + GCONF_VERSION=1.2.1 + LIBGNOME_VERSION=2.0 ++STARTUP_NOTIFICATION_VERSION=0.8 + + dnl Set various checks + dnl ======================================================== +@@ -4156,6 +4157,41 @@ + + AC_SUBST(MOZ_DEFAULT_TOOLKIT) + ++dnl ======================================================== ++dnl = startup-notification support module ++dnl ======================================================== ++ ++if test "$MOZ_ENABLE_GTK2" ++then ++ MOZ_ENABLE_STARTUP_NOTIFICATION= ++ ++ MOZ_ARG_ENABLE_BOOL(startup-notification, ++ [ --enable-startup-notification Enable startup-notification support (default: disabled) ], ++ MOZ_ENABLE_STARTUP_NOTIFICATION=force, ++ MOZ_ENABLE_STARTUP_NOTIFICATION=) ++ if test "$MOZ_ENABLE_STARTUP_NOTIFICATION" ++ then ++ PKG_CHECK_MODULES(MOZ_STARTUP_NOTIFICATION, ++ libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_VERSION, ++ [MOZ_ENABLE_STARTUP_NOTIFICATION=1], [ ++ if test "$MOZ_ENABLE_STARTUP_NOTIFICATION" = "force" ++ then ++ AC_MSG_ERROR([* * * Could not find startup-notification >= $STARTUP_NOTIFICATION_VERSION]) ++ fi ++ MOZ_ENABLE_STARTUP_NOTIFICATION= ++ ]) ++ fi ++ ++ if test "$MOZ_ENABLE_STARTUP_NOTIFICATION"; then ++ AC_DEFINE(MOZ_ENABLE_STARTUP_NOTIFICATION) ++ fi ++ ++ TK_LIBS="$TK_LIBS $MOZ_STARTUP_NOTIFICATION_LIBS" ++fi ++AC_SUBST(MOZ_ENABLE_STARTUP_NOTIFICATION) ++AC_SUBST(MOZ_STARTUP_NOTIFICATION_CFLAGS) ++AC_SUBST(MOZ_STARTUP_NOTIFICATION_LIBS) ++ + AC_SUBST(GTK_CONFIG) + AC_SUBST(TK_CFLAGS) + AC_SUBST(TK_LIBS) +--- widget/src/gtk2/nsWindow.cpp 2007-04-19 14:46:03.000000000 -0400 ++++ widget/src/gtk2/nsWindow.cpp 2007-07-03 18:01:36.000000000 -0400 +@@ -40,7 +40,7 @@ + #include "prlink.h" + + #include "nsWindow.h" +-#include "nsToolkit.h" ++#include "nsGTKToolkit.h" + #include "nsIRenderingContext.h" + #include "nsIRegion.h" + #include "nsIRollupListener.h" +@@ -58,6 +58,11 @@ + #include + #include + ++#ifdef MOZ_ENABLE_STARTUP_NOTIFICATION ++#define SN_API_NOT_YET_FROZEN ++#include ++#endif ++ + #include "gtk2xtbin.h" + + #include "nsIPrefService.h" +@@ -660,6 +665,75 @@ + return NS_ERROR_NOT_IMPLEMENTED; + } + ++typedef void (* SetUserTimeFunc)(GdkWindow* aWindow, guint32 aTimestamp); ++ ++// This will become obsolete when new GTK APIs are widely supported, ++// as described here: http://bugzilla.gnome.org/show_bug.cgi?id=347375 ++static void ++SetUserTimeAndStartupIDForActivatedWindow(GtkWidget* aWindow) ++{ ++ nsCOMPtr toolkit; ++ NS_GetCurrentToolkit(getter_AddRefs(toolkit)); ++ if (!toolkit) ++ return; ++ ++ nsGTKToolkit* GTKToolkit = NS_STATIC_CAST(nsGTKToolkit*, ++ NS_STATIC_CAST(nsIToolkit*, toolkit)); ++ nsCAutoString desktopStartupID; ++ GTKToolkit->GetDesktopStartupID(&desktopStartupID); ++ if (desktopStartupID.IsEmpty()) { ++ // We don't have the data we need. Fall back to an ++ // approximation ... using the timestamp of the remote command ++ // being received as a guess for the timestamp of the user event ++ // that triggered it. ++ PRUint32 timestamp = GTKToolkit->GetFocusTimestamp(); ++ if (timestamp) { ++ gdk_window_focus(aWindow->window, timestamp); ++ GTKToolkit->SetFocusTimestamp(0); ++ } ++ return; ++ } ++ ++#ifdef MOZ_ENABLE_STARTUP_NOTIFICATION ++ GdkDrawable* drawable = GDK_DRAWABLE(aWindow->window); ++ GtkWindow* win = GTK_WINDOW(aWindow); ++ if (!win) { ++ NS_WARNING("Passed in widget was not a GdkWindow!"); ++ return; ++ } ++ GdkScreen* screen = gtk_window_get_screen(win); ++ SnDisplay* snd = ++ sn_display_new(gdk_x11_drawable_get_xdisplay(drawable), nsnull, nsnull); ++ if (!snd) ++ return; ++ SnLauncheeContext* ctx = ++ sn_launchee_context_new(snd, gdk_screen_get_number(screen), ++ desktopStartupID.get()); ++ if (!ctx) { ++ sn_display_unref(snd); ++ return; ++ } ++ ++ if (sn_launchee_context_get_id_has_timestamp(ctx)) { ++ PRLibrary* gtkLibrary; ++ SetUserTimeFunc setUserTimeFunc = (SetUserTimeFunc) ++ PR_FindFunctionSymbolAndLibrary("gdk_x11_window_set_user_time", >kLibrary); ++ if (setUserTimeFunc) { ++ setUserTimeFunc(aWindow->window, sn_launchee_context_get_timestamp(ctx)); ++ PR_UnloadLibrary(gtkLibrary); ++ } ++ } ++ ++ sn_launchee_context_setup_window(ctx, gdk_x11_drawable_get_xid(drawable)); ++ sn_launchee_context_complete(ctx); ++ ++ sn_launchee_context_unref(ctx); ++ sn_display_unref(snd); ++#endif ++ ++ GTKToolkit->SetDesktopStartupID(EmptyCString()); ++} ++ + NS_IMETHODIMP + nsWindow::SetFocus(PRBool aRaise) + { +@@ -680,6 +754,10 @@ + // set properly. + GtkWidget *toplevelWidget = gtk_widget_get_toplevel(owningWidget); + ++ if (toplevelWidget && aRaise) { ++ SetUserTimeAndStartupIDForActivatedWindow(toplevelWidget); ++ } ++ + if (gRaiseWindows && aRaise && toplevelWidget && + !GTK_WIDGET_HAS_FOCUS(owningWidget) && + !GTK_WIDGET_HAS_FOCUS(toplevelWidget)) { +@@ -1167,7 +1245,7 @@ + + case NS_NATIVE_GRAPHIC: { + NS_ASSERTION(nsnull != mToolkit, "NULL toolkit, unable to get a GC"); +- return (void *)NS_STATIC_CAST(nsToolkit *, mToolkit)->GetSharedGC(); ++ return (void *)NS_STATIC_CAST(nsGTKToolkit *, mToolkit)->GetSharedGC(); + break; + } + +@@ -2802,13 +2880,18 @@ + // is shown. + // XXX that may or may not be true for GTK+ 2.x + if (mTransparencyBitmap) { +- ApplyTransparencyBitmap(); ++ ApplyTransparencyBitmap(); + } + + // unset our flag now that our window has been shown + mNeedsShow = PR_FALSE; + + if (mIsTopLevel) { ++ // Set up usertime/startupID metadata for the created window. ++ if (mWindowType != eWindowType_invisible) { ++ SetUserTimeAndStartupIDForActivatedWindow(mShell); ++ } ++ + moz_drawingarea_set_visibility(mDrawingarea, aAction); + gtk_widget_show(GTK_WIDGET(mContainer)); + gtk_widget_show(mShell); +--- widget/src/gtk2/Makefile.in 2006-06-17 11:16:14.000000000 -0400 ++++ widget/src/gtk2/Makefile.in 2007-07-03 18:01:36.000000000 -0400 +@@ -97,6 +97,7 @@ + $(MOZ_COMPONENT_LIBS) \ + -lgkgfx \ + -lgtkxtbin \ ++ $(MOZ_STARTUP_NOTIFICATION_LIBS) \ + $(XLDFLAGS) \ + $(XLIBS) \ + $(MOZ_GTK2_LIBS) +@@ -107,14 +108,15 @@ + + EXPORTS = \ + nsIGdkPixbufImage.h \ ++ nsGTKToolkit.h \ + mozdrawingarea.h \ + mozcontainer.h \ + $(NULL) + + include $(topsrcdir)/config/rules.mk + +-CFLAGS += $(MOZ_GTK2_CFLAGS) +-CXXFLAGS += $(MOZ_GTK2_CFLAGS) ++CFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_STARTUP_NOTIFICATION_CFLAGS) ++CXXFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_STARTUP_NOTIFICATION_CFLAGS) + + DEFINES += -DUSE_XIM + +--- widget/src/gtk2/nsToolkit.cpp 2004-04-18 18:00:17.000000000 -0400 ++++ widget/src/gtk2/nsToolkit.cpp 2007-07-03 18:01:36.000000000 -0400 +@@ -38,7 +38,7 @@ + * ***** END LICENSE BLOCK ***** */ + + #include "nscore.h" // needed for 'nsnull' +-#include "nsToolkit.h" ++#include "nsGTKToolkit.h" + + // + // Static thread local storage index of the Toolkit +@@ -51,9 +51,10 @@ + // constructor + // + //------------------------------------------------------------------------- +-nsToolkit::nsToolkit() ++nsGTKToolkit::nsGTKToolkit() + { + mSharedGC = nsnull; ++ mFocusTimestamp = 0; + } + + //------------------------------------------------------------------------- +@@ -61,7 +62,7 @@ + // destructor + // + //------------------------------------------------------------------------- +-nsToolkit::~nsToolkit() ++nsGTKToolkit::~nsGTKToolkit() + { + if (mSharedGC) { + gdk_gc_unref(mSharedGC); +@@ -77,9 +78,9 @@ + // + //------------------------------------------------------------------------- + +-NS_IMPL_ISUPPORTS1(nsToolkit, nsIToolkit) ++NS_IMPL_ISUPPORTS1(nsGTKToolkit, nsIToolkit) + +-void nsToolkit::CreateSharedGC(void) ++void nsGTKToolkit::CreateSharedGC(void) + { + GdkPixmap *pixmap; + +@@ -91,7 +92,7 @@ + gdk_pixmap_unref(pixmap); + } + +-GdkGC *nsToolkit::GetSharedGC(void) ++GdkGC *nsGTKToolkit::GetSharedGC(void) + { + return gdk_gc_ref(mSharedGC); + } +@@ -100,7 +101,7 @@ + // + // + //------------------------------------------------------------------------- +-NS_IMETHODIMP nsToolkit::Init(PRThread *aThread) ++NS_IMETHODIMP nsGTKToolkit::Init(PRThread *aThread) + { + CreateSharedGC(); + +@@ -135,7 +136,7 @@ + // Create a new toolkit for this thread... + // + if (!toolkit) { +- toolkit = new nsToolkit(); ++ toolkit = new nsGTKToolkit(); + + if (!toolkit) { + rv = NS_ERROR_OUT_OF_MEMORY; +--- widget/src/xremoteclient/mozilla-xremote-client.cpp 2005-04-04 15:08:51.000000000 -0400 ++++ widget/src/xremoteclient/mozilla-xremote-client.cpp 2007-07-03 18:01:36.000000000 -0400 +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include + #ifdef MOZ_WIDGET_PHOTON + #include "PhRemoteClient.h" + #else +@@ -99,7 +100,7 @@ + // send the command - it doesn't get any easier than this + PRBool success = PR_FALSE; + char *error = 0; +- rv = client.SendCommand(browser, username, profile, command, ++ rv = client.SendCommand(browser, username, profile, command, nsnull, + &error, &success); + + // failed to send command +--- widget/src/xremoteclient/XRemoteClient.cpp 2006-03-30 03:01:13.000000000 -0500 ++++ widget/src/xremoteclient/XRemoteClient.cpp 2007-07-03 18:01:36.000000000 -0400 +@@ -173,6 +173,7 @@ + nsresult + XRemoteClient::SendCommand (const char *aProgram, const char *aUsername, + const char *aProfile, const char *aCommand, ++ const char* aDesktopStartupID, + char **aResponse, PRBool *aWindowFound) + { + PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::SendCommand")); +@@ -198,7 +199,7 @@ + + if (NS_SUCCEEDED(rv)) { + // send our command +- rv = DoSendCommand(w, aCommand, aResponse, &destroyed); ++ rv = DoSendCommand(w, aCommand, aDesktopStartupID, aResponse, &destroyed); + + // if the window was destroyed, don't bother trying to free the + // lock. +@@ -217,6 +218,7 @@ + XRemoteClient::SendCommandLine (const char *aProgram, const char *aUsername, + const char *aProfile, + PRInt32 argc, char **argv, ++ const char* aDesktopStartupID, + char **aResponse, PRBool *aWindowFound) + { + PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::SendCommandLine")); +@@ -242,7 +244,7 @@ + + if (NS_SUCCEEDED(rv)) { + // send our command +- rv = DoSendCommandLine(w, argc, argv, aResponse, &destroyed); ++ rv = DoSendCommandLine(w, argc, argv, aDesktopStartupID, aResponse, &destroyed); + + // if the window was destroyed, don't bother trying to free the + // lock. +@@ -643,6 +645,7 @@ + + nsresult + XRemoteClient::DoSendCommand(Window aWindow, const char *aCommand, ++ const char* aDesktopStartupID, + char **aResponse, PRBool *aDestroyed) + { + *aDestroyed = PR_FALSE; +@@ -651,9 +654,28 @@ + ("(writing " MOZILLA_COMMAND_PROP " \"%s\" to 0x%x)\n", + aCommand, (unsigned int) aWindow)); + ++ // We add the DESKTOP_STARTUP_ID setting as an extra line of ++ // the command string. Firefox ignores all lines but the first. ++ static char desktopStartupPrefix[] = "\nDESKTOP_STARTUP_ID="; ++ ++ PRInt32 len = strlen(aCommand); ++ if (aDesktopStartupID) { ++ len += sizeof(desktopStartupPrefix) - 1 + strlen(aDesktopStartupID); ++ } ++ char* buffer = (char*)malloc(len + 1); ++ if (!buffer) ++ return NS_ERROR_OUT_OF_MEMORY; ++ ++ strcpy(buffer, aCommand); ++ if (aDesktopStartupID) { ++ strcat(buffer, desktopStartupPrefix); ++ strcat(buffer, aDesktopStartupID); ++ } ++ + XChangeProperty (mDisplay, aWindow, mMozCommandAtom, XA_STRING, 8, +- PropModeReplace, (unsigned char *)aCommand, +- strlen(aCommand)); ++ PropModeReplace, (unsigned char *)buffer, len); ++ ++ free(buffer); + + if (!WaitForResponse(aWindow, aResponse, aDestroyed, mMozCommandAtom)) + return NS_ERROR_FAILURE; +@@ -663,7 +685,7 @@ + + /* like strcpy, but return the char after the final null */ + static char* +-estrcpy(char* s, char* d) ++estrcpy(const char* s, char* d) + { + while (*s) + *d++ = *s++; +@@ -674,6 +696,7 @@ + + nsresult + XRemoteClient::DoSendCommandLine(Window aWindow, PRInt32 argc, char **argv, ++ const char* aDesktopStartupID, + char **aResponse, PRBool *aDestroyed) + { + int i; +@@ -690,9 +713,16 @@ + // [argc][offsetargv0][offsetargv1...]\0\0argv[1]...\0 + // (offset is from the beginning of the buffer) + ++ static char desktopStartupPrefix[] = " DESKTOP_STARTUP_ID="; ++ + PRInt32 argvlen = strlen(cwdbuf); +- for (i = 0; i < argc; ++i) +- argvlen += strlen(argv[i]); ++ for (i = 0; i < argc; ++i) { ++ PRInt32 len = strlen(argv[i]); ++ if (i == 0 && aDesktopStartupID) { ++ len += sizeof(desktopStartupPrefix) - 1 + strlen(aDesktopStartupID); ++ } ++ argvlen += len; ++ } + + PRInt32* buffer = (PRInt32*) malloc(argvlen + argc + 1 + + sizeof(PRInt32) * (argc + 1)); +@@ -708,6 +738,10 @@ + for (int i = 0; i < argc; ++i) { + buffer[i + 1] = TO_LITTLE_ENDIAN32(bufend - ((char*) buffer)); + bufend = estrcpy(argv[i], bufend); ++ if (i == 0 && aDesktopStartupID) { ++ bufend = estrcpy(desktopStartupPrefix, bufend - 1); ++ bufend = estrcpy(aDesktopStartupID, bufend - 1); ++ } + } + + #ifdef DEBUG_bsmedberg +--- widget/src/xremoteclient/nsRemoteClient.h 2005-04-04 15:08:51.000000000 -0400 ++++ widget/src/xremoteclient/nsRemoteClient.h 2007-07-03 18:01:36.000000000 -0400 +@@ -76,6 +76,10 @@ + * @param aCommand This is the command that is passed to the server. + * Please see the additional information located at: + * http://www.mozilla.org/unix/remote.html ++ * ++ * @param aDesktopStartupID the contents of the DESKTOP_STARTUP_ID environment ++ * variable defined by the Startup Notification specification ++ * http://standards.freedesktop.org/startup-notification-spec/startup-notification-0.1.txt + * + * @param aResponse If there is a response, it will be here. This + * includes error messages. The string is allocated using stdlib +@@ -85,11 +89,16 @@ + */ + virtual nsresult SendCommand(const char *aProgram, const char *aUsername, + const char *aProfile, const char *aCommand, ++ const char* aDesktopStartupID, + char **aResponse, PRBool *aSucceeded) = 0; + + /** + * Send a complete command line to a running instance. + * ++ * @param aDesktopStartupID the contents of the DESKTOP_STARTUP_ID environment ++ * variable defined by the Startup Notification specification ++ * http://standards.freedesktop.org/startup-notification-spec/startup-notification-0.1.txt ++ * + * @see sendCommand + * @param argc The number of command-line arguments. + * +@@ -97,6 +106,7 @@ + virtual nsresult SendCommandLine(const char *aProgram, const char *aUsername, + const char *aProfile, + PRInt32 argc, char **argv, ++ const char* aDesktopStartupID, + char **aResponse, PRBool *aSucceeded) = 0; + }; + +--- widget/src/xremoteclient/XRemoteClient.h 2006-03-30 03:01:13.000000000 -0500 ++++ widget/src/xremoteclient/XRemoteClient.h 2007-07-03 18:01:36.000000000 -0400 +@@ -48,10 +48,12 @@ + virtual nsresult Init(); + virtual nsresult SendCommand(const char *aProgram, const char *aUsername, + const char *aProfile, const char *aCommand, ++ const char* aDesktopStartupID, + char **aResponse, PRBool *aSucceeded); + virtual nsresult SendCommandLine(const char *aProgram, const char *aUsername, + const char *aProfile, + PRInt32 argc, char **argv, ++ const char* aDesktopStartupID, + char **aResponse, PRBool *aSucceeded); + void Shutdown(); + +@@ -67,10 +69,12 @@ + PRBool aSupportsCommandLine); + nsresult DoSendCommand (Window aWindow, + const char *aCommand, ++ const char* aDesktopStartupID, + char **aResponse, + PRBool *aDestroyed); + nsresult DoSendCommandLine(Window aWindow, + PRInt32 argc, char **argv, ++ const char* aDesktopStartupID, + char **aResponse, + PRBool *aDestroyed); + PRBool WaitForResponse (Window aWindow, char **aResponse, +--- /dev/null 2007-07-05 17:03:04.116204904 -0400 ++++ widget/src/gtk2/nsGTKToolkit.h 2007-07-03 18:01:36.000000000 -0400 +@@ -0,0 +1,87 @@ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* vim:expandtab:shiftwidth=4:tabstop=4: ++ */ ++/* ***** BEGIN LICENSE BLOCK ***** ++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++ * ++ * The contents of this file are subject to the Mozilla Public License Version ++ * 1.1 (the "License"); you may not use this file except in compliance with ++ * the License. You may obtain a copy of the License at ++ * http://www.mozilla.org/MPL/ ++ * ++ * Software distributed under the License is distributed on an "AS IS" basis, ++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++ * for the specific language governing rights and limitations under the ++ * License. ++ * ++ * The Original Code is mozilla.org code. ++ * ++ * The Initial Developer of the Original Code is ++ * Netscape Communications Corporation. ++ * Portions created by the Initial Developer are Copyright (C) 1998 ++ * the Initial Developer. All Rights Reserved. ++ * ++ * Contributor(s): ++ * ++ * Alternatively, the contents of this file may be used under the terms of ++ * either the GNU General Public License Version 2 or later (the "GPL"), or ++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++ * in which case the provisions of the GPL or the LGPL are applicable instead ++ * of those above. If you wish to allow use of your version of this file only ++ * under the terms of either the GPL or the LGPL, and not to allow others to ++ * use your version of this file under the terms of the MPL, indicate your ++ * decision by deleting the provisions above and replace them with the notice ++ * and other provisions required by the GPL or the LGPL. If you do not delete ++ * the provisions above, a recipient may use your version of this file under ++ * the terms of any one of the MPL, the GPL or the LGPL. ++ * ++ * ***** END LICENSE BLOCK ***** */ ++ ++#ifndef GTKTOOLKIT_H ++#define GTKTOOLKIT_H ++ ++#include "nsIToolkit.h" ++#include "nsString.h" ++#include ++ ++/** ++ * Wrapper around the thread running the message pump. ++ * The toolkit abstraction is necessary because the message pump must ++ * execute within the same thread that created the widget under Win32. ++ */ ++ ++class nsGTKToolkit : public nsIToolkit ++{ ++public: ++ nsGTKToolkit(); ++ virtual ~nsGTKToolkit(); ++ ++ NS_DECL_ISUPPORTS ++ ++ NS_IMETHOD Init(PRThread *aThread); ++ ++ void CreateSharedGC(void); ++ GdkGC *GetSharedGC(void); ++ ++ /** ++ * Get/set our value of DESKTOP_STARTUP_ID. When non-empty, this is applied ++ * to the next toplevel window to be shown or focused (and then immediately ++ * cleared). ++ */ ++ void SetDesktopStartupID(const nsACString& aID) { mDesktopStartupID = aID; } ++ void GetDesktopStartupID(nsACString* aID) { *aID = mDesktopStartupID; } ++ ++ /** ++ * Get/set the timestamp value to be used, if non-zero, to focus the ++ * next top-level window to be shown or focused (upon which it is cleared). ++ */ ++ void SetFocusTimestamp(PRUint32 aTimestamp) { mFocusTimestamp = aTimestamp; } ++ PRUint32 GetFocusTimestamp() { return mFocusTimestamp; } ++ ++private: ++ GdkGC *mSharedGC; ++ nsCString mDesktopStartupID; ++ PRUint32 mFocusTimestamp; ++}; ++ ++#endif // GTKTOOLKIT_H diff --git a/firefox-redhat-default-prefs.js b/firefox-redhat-default-prefs.js index b4d1ca7..9eee505 100644 --- a/firefox-redhat-default-prefs.js +++ b/firefox-redhat-default-prefs.js @@ -6,3 +6,6 @@ pref("general.smoothScroll", true); pref("general.useragent.vendor", "Fedora"); pref("general.useragent.vendorSub", "FIREFOX_RPM_VR"); pref("intl.locale.matchOS", true); +pref("browser.startup.homepage", "http://start.fedoraproject.org/"); +pref("startup.homepage_override_url", "http://start.fedoraproject.org/"); +pref("startup.homepage_welcome_url", "http://start.fedoraproject.org/"); diff --git a/firefox.spec b/firefox.spec index de65c8d..b068e41 100644 --- a/firefox.spec +++ b/firefox.spec @@ -12,7 +12,7 @@ Summary: Mozilla Firefox Web browser. Name: firefox Version: 2.0.0.6 -Release: 8%{?dist} +Release: 9%{?dist} URL: http://www.mozilla.org/projects/firefox/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Group: Applications/Internet @@ -72,6 +72,7 @@ Patch102: firefox-1.5-theme-change.patch Patch104: firefox-1.5-ppc64.patch Patch105: firefox-2.0-dnd.patch Patch106: firefox-2.0-indicator-crash.patch +Patch110: firefox-2.0-startup-notify.patch %if %{official_branding} # Required by Mozilla Corporation @@ -174,6 +175,7 @@ removed in favor of xulrunner-devel. %patch104 -p1 -b .ppc64 %patch105 -p0 -b .dnd %patch106 -p1 -b .indicator-crash +%patch110 -p0 -b .startup-notify # For branding specific patches. @@ -440,6 +442,9 @@ fi #--------------------------------------------------------------------- %changelog +* Mon Sep 24 2007 Christopher Aillon 2.0.0.6-9 +- Startup notification support + * Tue Sep 11 2007 Christopher Aillon 2.0.0.6-8 - Fix crashes when using GTK+ themes containing a gtkrc which specify GtkOptionMenu::indicator_size and GtkOptionMenu::indicator_spacing