forked from pool/MozillaFirefox
1076 lines
34 KiB
Diff
1076 lines
34 KiB
Diff
|
From: Robert O'Callahan <rocallahan@novell.com>
|
||
|
Subject: implement startup-notification
|
||
|
References:
|
||
|
https://bugzilla.novell.com/show_bug.cgi?id=115417
|
||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=223492
|
||
|
|
||
|
Index: configure.in
|
||
|
================================================================================
|
||
|
--- config/autoconf.mk.in
|
||
|
+++ config/autoconf.mk.in
|
||
|
@@ -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@
|
||
|
|
||
|
--- configure.in
|
||
|
+++ configure.in
|
||
|
@@ -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 ========================================================
|
||
|
@@ -4088,6 +4089,42 @@
|
||
|
|
||
|
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)
|
||
|
--- toolkit/components/remote/Makefile.in
|
||
|
+++ toolkit/components/remote/Makefile.in
|
||
|
@@ -56,8 +56,9 @@
|
||
|
string \
|
||
|
appcomps \
|
||
|
toolkitcomps \
|
||
|
- appcomps \
|
||
|
+ appshell \
|
||
|
xulapp \
|
||
|
+ layout \
|
||
|
widget \
|
||
|
gfx \
|
||
|
dom \
|
||
|
--- toolkit/components/remote/nsGTKRemoteService.cpp
|
||
|
+++ toolkit/components/remote/nsGTKRemoteService.cpp
|
||
|
@@ -50,7 +50,7 @@
|
||
|
|
||
|
#include "nsIBaseWindow.h"
|
||
|
#include "nsIDocShell.h"
|
||
|
-#include "nsIDOMWindow.h"
|
||
|
+#include "nsPIDOMWindow.h"
|
||
|
#include "nsIGenericFactory.h"
|
||
|
#include "nsILocalFile.h"
|
||
|
#include "nsIObserverService.h"
|
||
|
@@ -58,6 +58,8 @@
|
||
|
#include "nsIServiceManager.h"
|
||
|
#include "nsIWeakReference.h"
|
||
|
#include "nsIWidget.h"
|
||
|
+#include "nsIAppShellService.h"
|
||
|
+#include "nsAppShellCID.h"
|
||
|
|
||
|
#include "nsCOMPtr.h"
|
||
|
#include "nsString.h"
|
||
|
@@ -72,6 +74,10 @@
|
||
|
#include "nsISuiteRemoteService.h"
|
||
|
#endif
|
||
|
|
||
|
+#ifdef MOZ_WIDGET_GTK2
|
||
|
+#include "nsGTKToolkit.h"
|
||
|
+#endif
|
||
|
+
|
||
|
#define MOZILLA_VERSION_PROP "_MOZILLA_VERSION"
|
||
|
#define MOZILLA_LOCK_PROP "_MOZILLA_LOCK"
|
||
|
#define MOZILLA_COMMAND_PROP "_MOZILLA_COMMAND"
|
||
|
@@ -155,20 +161,44 @@
|
||
|
return PL_DHASH_NEXT;
|
||
|
}
|
||
|
|
||
|
-NS_IMETHODIMP
|
||
|
-nsGTKRemoteService::RegisterWindow(nsIDOMWindow* aWindow)
|
||
|
+static nsIWidget* GetMainWidget(nsIDOMWindow* aWindow)
|
||
|
{
|
||
|
// get the native window for this instance
|
||
|
nsCOMPtr<nsIScriptGlobalObject> scriptObject
|
||
|
(do_QueryInterface(aWindow));
|
||
|
- NS_ENSURE_TRUE(scriptObject, NS_ERROR_FAILURE);
|
||
|
+ NS_ENSURE_TRUE(scriptObject, nsnull);
|
||
|
|
||
|
nsCOMPtr<nsIBaseWindow> baseWindow
|
||
|
(do_QueryInterface(scriptObject->GetDocShell()));
|
||
|
- NS_ENSURE_TRUE(baseWindow, NS_ERROR_FAILURE);
|
||
|
+ NS_ENSURE_TRUE(baseWindow, nsnull);
|
||
|
|
||
|
nsCOMPtr<nsIWidget> mainWidget;
|
||
|
baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
|
||
|
+ return mainWidget;
|
||
|
+}
|
||
|
+
|
||
|
+static nsGTKToolkit* GetGTKToolkit()
|
||
|
+{
|
||
|
+ nsCOMPtr<nsIAppShellService> svc = do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
|
||
|
+ if (!svc)
|
||
|
+ return nsnull;
|
||
|
+ nsCOMPtr<nsIDOMWindowInternal> 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)
|
||
|
+{
|
||
|
+ nsIWidget* mainWidget = GetMainWidget(aWindow);
|
||
|
NS_ENSURE_TRUE(mainWidget, NS_ERROR_FAILURE);
|
||
|
|
||
|
// walk up the widget tree and find the toplevel window in the
|
||
|
@@ -260,7 +290,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 +313,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 +396,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 +410,8 @@
|
||
|
if (aWindow)
|
||
|
cmdline->SetWindowContext(aWindow);
|
||
|
|
||
|
+ SetDesktopStartupIDOrTimestamp(desktopStartupID, aTimestamp);
|
||
|
+
|
||
|
rv = cmdline->Run();
|
||
|
if (NS_ERROR_ABORT == rv)
|
||
|
return "500 command not parseable";
|
||
|
@@ -333,7 +423,8 @@
|
||
|
}
|
||
|
|
||
|
const char*
|
||
|
-nsGTKRemoteService::HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow)
|
||
|
+nsGTKRemoteService::HandleCommandLine(char* aBuffer, nsIDOMWindow* aWindow,
|
||
|
+ PRUint32 aTimestamp)
|
||
|
{
|
||
|
nsresult rv;
|
||
|
|
||
|
@@ -364,6 +455,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 +465,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 +485,10 @@
|
||
|
if (aWindow)
|
||
|
cmdline->SetWindowContext(aWindow);
|
||
|
|
||
|
+ SetDesktopStartupIDOrTimestamp(desktopStartupID, aTimestamp);
|
||
|
+
|
||
|
rv = cmdline->Run();
|
||
|
+
|
||
|
if (NS_ERROR_ABORT == rv)
|
||
|
return "500 command not parseable";
|
||
|
|
||
|
@@ -486,7 +588,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 +633,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
|
||
|
+++ toolkit/components/remote/nsGTKRemoteService.h
|
||
|
@@ -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/library/Makefile.in
|
||
|
+++ toolkit/library/Makefile.in
|
||
|
@@ -344,6 +344,10 @@
|
||
|
EXTRA_DSO_LDOPTS += $(XLDFLAGS) $(XLIBS) $(MOZ_GTK_LDFLAGS) $(MOZ_XFT_LIBS) $(MOZ_GTK2_LIBS) $(XT_LIBS)
|
||
|
endif
|
||
|
|
||
|
+ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
|
||
|
+EXTRA_DSO_LDOPTS += $(MOZ_STARTUP_NOTIFICATION_LIBS)
|
||
|
+endif
|
||
|
+
|
||
|
ifdef MOZ_ENABLE_XPRINT
|
||
|
EXTRA_DSO_LDOPTS += $(MOZ_XPRINT_LDFLAGS)
|
||
|
endif
|
||
|
--- toolkit/xre/Makefile.in
|
||
|
+++ toolkit/xre/Makefile.in
|
||
|
@@ -69,6 +69,7 @@
|
||
|
shellservice \
|
||
|
string \
|
||
|
uriloader \
|
||
|
+ layout \
|
||
|
widget \
|
||
|
windowwatcher \
|
||
|
xpcom \
|
||
|
--- toolkit/xre/nsAppRunner.cpp
|
||
|
+++ toolkit/xre/nsAppRunner.cpp
|
||
|
@@ -96,6 +96,7 @@
|
||
|
#include "nsIWindowWatcher.h"
|
||
|
#include "nsIXULAppInfo.h"
|
||
|
#include "nsIXULRuntime.h"
|
||
|
+#include "nsIScriptGlobalObject.h"
|
||
|
|
||
|
#include "nsCRT.h"
|
||
|
#include "nsCOMPtr.h"
|
||
|
@@ -112,6 +113,12 @@
|
||
|
#include "nsXULAppAPI.h"
|
||
|
#include "nsXREDirProvider.h"
|
||
|
#include "nsToolkitCompsCID.h"
|
||
|
+#include "nsPIDOMWindow.h"
|
||
|
+#include "nsIDOMWindowInternal.h"
|
||
|
+#include "nsIBaseWindow.h"
|
||
|
+#include "nsIWidget.h"
|
||
|
+#include "nsIDocShell.h"
|
||
|
+#include "nsAppShellCID.h"
|
||
|
|
||
|
#include "nsINIParser.h"
|
||
|
|
||
|
@@ -249,6 +256,9 @@
|
||
|
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
|
||
|
#include <gtk/gtk.h>
|
||
|
#endif //MOZ_WIDGET_GTK || MOZ_WIDGET_GTK2
|
||
|
+#if defined(MOZ_WIDGET_GTK2)
|
||
|
+#include "nsGTKToolkit.h"
|
||
|
+#endif
|
||
|
|
||
|
#if defined(MOZ_WIDGET_QT)
|
||
|
#include <qapplication.h>
|
||
|
@@ -916,7 +926,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;
|
||
|
@@ -957,7 +967,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",
|
||
|
@@ -974,7 +984,7 @@
|
||
|
}
|
||
|
|
||
|
static PRBool
|
||
|
-RemoteCommandLine()
|
||
|
+RemoteCommandLine(const char* aDesktopStartupID)
|
||
|
{
|
||
|
nsresult rv;
|
||
|
ArgResult ar;
|
||
|
@@ -1006,7 +1016,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)
|
||
|
@@ -1865,6 +1875,41 @@
|
||
|
#ifdef MOZ_WIDGET_GTK2
|
||
|
#include "prlink.h"
|
||
|
typedef void (*_g_set_application_name_fn)(const gchar *application_name);
|
||
|
+
|
||
|
+static nsIWidget* GetMainWidget(nsIDOMWindow* aWindow)
|
||
|
+{
|
||
|
+ // get the native window for this instance
|
||
|
+ nsCOMPtr<nsIScriptGlobalObject> scriptObject
|
||
|
+ (do_QueryInterface(aWindow));
|
||
|
+ NS_ENSURE_TRUE(scriptObject, nsnull);
|
||
|
+
|
||
|
+ nsCOMPtr<nsIBaseWindow> baseWindow
|
||
|
+ (do_QueryInterface(scriptObject->GetDocShell()));
|
||
|
+ NS_ENSURE_TRUE(baseWindow, nsnull);
|
||
|
+
|
||
|
+ nsCOMPtr<nsIWidget> mainWidget;
|
||
|
+ baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
|
||
|
+ return mainWidget;
|
||
|
+}
|
||
|
+
|
||
|
+static nsGTKToolkit* GetGTKToolkit()
|
||
|
+{
|
||
|
+ nsCOMPtr<nsIAppShellService> svc = do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
|
||
|
+ if (!svc)
|
||
|
+ return nsnull;
|
||
|
+ nsCOMPtr<nsIDOMWindowInternal> 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
|
||
|
@@ -2033,6 +2078,19 @@
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2) || defined(MOZ_ENABLE_XREMOTE)
|
||
|
+ // Stash DESKTOP_STARTUP_ID becaus gtk_init will clear it.
|
||
|
+#define HAVE_DESKTOP_STARTUP_ID
|
||
|
+ char* desktopStartupID = PR_GetEnv("DESKTOP_STARTUP_ID");
|
||
|
+ if (desktopStartupID) {
|
||
|
+ if (desktopStartupID[0] == 0) {
|
||
|
+ desktopStartupID = nsnull;
|
||
|
+ } else {
|
||
|
+ desktopStartupID = strdup(desktopStartupID);
|
||
|
+ }
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_GTK2)
|
||
|
// setup for private colormap. Ideally we'd like to do this
|
||
|
// in nsAppShell::Create, but we need to get in before gtk
|
||
|
@@ -2058,6 +2116,7 @@
|
||
|
if (glib2) {
|
||
|
PR_UnloadLibrary(glib2);
|
||
|
}
|
||
|
+ gtk_window_set_auto_startup_notification(PR_FALSE);
|
||
|
#endif
|
||
|
|
||
|
gtk_widget_set_default_visual(gdk_rgb_get_visual());
|
||
|
@@ -2122,12 +2181,12 @@
|
||
|
return 1;
|
||
|
}
|
||
|
if (ar) {
|
||
|
- return HandleRemoteArgument(xremotearg);
|
||
|
+ return HandleRemoteArgument(xremotearg, desktopStartupID);
|
||
|
}
|
||
|
|
||
|
if (!PR_GetEnv("MOZ_NO_REMOTE")) {
|
||
|
// Try to remote the entire command line. If this fails, start up normally.
|
||
|
- if (RemoteCommandLine())
|
||
|
+ if (RemoteCommandLine(desktopStartupID))
|
||
|
return 0;
|
||
|
}
|
||
|
#endif
|
||
|
@@ -2329,6 +2388,13 @@
|
||
|
NS_TIMELINE_LEAVE("appStartup->CreateHiddenWindow");
|
||
|
NS_ENSURE_SUCCESS(rv, 1);
|
||
|
|
||
|
+#if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK2)
|
||
|
+ nsRefPtr<nsGTKToolkit> toolkit = GetGTKToolkit();
|
||
|
+ if (toolkit && desktopStartupID) {
|
||
|
+ toolkit->SetDesktopStartupID(nsDependentCString(desktopStartupID));
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
// Extension Compatibility Checking and Startup
|
||
|
if (gAppData->flags & NS_XRE_ENABLE_EXTENSION_MANAGER) {
|
||
|
nsCOMPtr<nsIExtensionManager> em(do_GetService("@mozilla.org/extensions/manager;1"));
|
||
|
@@ -2505,9 +2571,28 @@
|
||
|
}
|
||
|
#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);
|
||
|
return rv == NS_ERROR_LAUNCHED_CHILD_PROCESS ? 0 : 1;
|
||
|
}
|
||
|
|
||
|
+#ifdef HAVE_DESKTOP_STARTUP_ID
|
||
|
+ free(desktopStartupID);
|
||
|
+#endif
|
||
|
+
|
||
|
return NS_FAILED(rv) ? 1 : 0;
|
||
|
}
|
||
|
--- widget/src/gtk2/Makefile.in
|
||
|
+++ widget/src/gtk2/Makefile.in
|
||
|
@@ -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/nsGTKToolkit.h
|
||
|
+++ widget/src/gtk2/nsGTKToolkit.h
|
||
|
@@ -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 <gtk/gtk.h>
|
||
|
+
|
||
|
+/**
|
||
|
+ * 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
|
||
|
--- widget/src/gtk2/nsToolkit.cpp
|
||
|
+++ widget/src/gtk2/nsToolkit.cpp
|
||
|
@@ -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/gtk2/nsWindow.cpp
|
||
|
+++ widget/src/gtk2/nsWindow.cpp
|
||
|
@@ -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 <gdk/gdkx.h>
|
||
|
#include <gdk/gdkkeysyms.h>
|
||
|
|
||
|
+#ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
|
||
|
+#define SN_API_NOT_YET_FROZEN
|
||
|
+#include <startup-notification-1.0/libsn/sn.h>
|
||
|
+#endif
|
||
|
+
|
||
|
#include "gtk2xtbin.h"
|
||
|
|
||
|
#include "nsIPrefService.h"
|
||
|
@@ -655,6 +660,70 @@
|
||
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||
|
}
|
||
|
|
||
|
+typedef void (* SetUserTimeFunc)(GdkWindow* aWindow, guint32 aTimestamp);
|
||
|
+
|
||
|
+static void
|
||
|
+SetUserTimeAndStartupIDForActivatedWindow(GtkWidget* aWindow)
|
||
|
+{
|
||
|
+ nsCOMPtr<nsIToolkit> 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()) {
|
||
|
+ 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)
|
||
|
{
|
||
|
@@ -675,10 +744,15 @@
|
||
|
// 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))
|
||
|
+ !GTK_WIDGET_HAS_FOCUS(toplevelWidget)) {
|
||
|
GetAttention(-1);
|
||
|
+ }
|
||
|
|
||
|
nsWindow *owningWindow = get_window_for_gtk_widget(owningWidget);
|
||
|
if (!owningWindow)
|
||
|
@@ -1147,7 +1221,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;
|
||
|
}
|
||
|
|
||
|
@@ -2755,7 +2829,7 @@
|
||
|
// 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
|
||
|
@@ -2765,6 +2839,11 @@
|
||
|
moz_drawingarea_set_visibility(mDrawingarea, aAction);
|
||
|
gtk_widget_show(GTK_WIDGET(mContainer));
|
||
|
gtk_widget_show(mShell);
|
||
|
+
|
||
|
+ // Set up usertime/startupID metadata for the created window.
|
||
|
+ if (mWindowType != eWindowType_invisible) {
|
||
|
+ SetUserTimeAndStartupIDForActivatedWindow(mShell);
|
||
|
+ }
|
||
|
}
|
||
|
else if (mContainer) {
|
||
|
moz_drawingarea_set_visibility(mDrawingarea, TRUE);
|
||
|
--- widget/src/xremoteclient/XRemoteClient.cpp
|
||
|
+++ widget/src/xremoteclient/XRemoteClient.cpp
|
||
|
@@ -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...]<workingdir>\0<argv[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 += strlen(desktopStartupPrefix) + 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/XRemoteClient.h
|
||
|
+++ widget/src/xremoteclient/XRemoteClient.h
|
||
|
@@ -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,
|
||
|
--- widget/src/xremoteclient/mozilla-xremote-client.cpp
|
||
|
+++ widget/src/xremoteclient/mozilla-xremote-client.cpp
|
||
|
@@ -40,6 +40,7 @@
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <plgetopt.h>
|
||
|
+#include <prenv.h>
|
||
|
#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/nsRemoteClient.h
|
||
|
+++ widget/src/xremoteclient/nsRemoteClient.h
|
||
|
@@ -85,6 +85,7 @@
|
||
|
*/
|
||
|
virtual nsresult SendCommand(const char *aProgram, const char *aUsername,
|
||
|
const char *aProfile, const char *aCommand,
|
||
|
+ const char* aDesktopStartupID,
|
||
|
char **aResponse, PRBool *aSucceeded) = 0;
|
||
|
|
||
|
/**
|
||
|
@@ -97,6 +98,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;
|
||
|
};
|
||
|
|