264 lines
8.6 KiB
C++
264 lines
8.6 KiB
C++
/* ***** 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
|
|
* Christopher Blizzard. Portions created by Christopher Blizzard are Copyright (C) Christopher Blizzard. All Rights Reserved.
|
|
* Portions created by the Initial Developer are Copyright (C) 2001
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Christopher Blizzard <blizzard@mozilla.org>
|
|
*
|
|
* 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 ***** */
|
|
|
|
#include <X11/Xatom.h> // for XA_STRING
|
|
#include <stdlib.h>
|
|
#include <nsIWidget.h>
|
|
#include <nsIXRemoteService.h>
|
|
#include <nsCOMPtr.h>
|
|
#include <nsIServiceManager.h>
|
|
#include <prprf.h>
|
|
#include <prenv.h>
|
|
#include "nsGtkMozRemoteHelper.h"
|
|
#include "nsCRT.h"
|
|
|
|
#define MOZILLA_VERSION_PROP "_MOZILLA_VERSION"
|
|
#define MOZILLA_LOCK_PROP "_MOZILLA_LOCK"
|
|
#define MOZILLA_COMMAND_PROP "_MOZILLA_COMMAND"
|
|
#define MOZILLA_RESPONSE_PROP "_MOZILLA_RESPONSE"
|
|
#define MOZILLA_USER_PROP "_MOZILLA_USER"
|
|
#define MOZILLA_PROFILE_PROP "_MOZILLA_PROFILE"
|
|
#define MOZILLA_PROGRAM_PROP "_MOZILLA_PROGRAM"
|
|
|
|
Atom nsGtkMozRemoteHelper::sMozVersionAtom = 0;
|
|
Atom nsGtkMozRemoteHelper::sMozLockAtom = 0;
|
|
Atom nsGtkMozRemoteHelper::sMozCommandAtom = 0;
|
|
Atom nsGtkMozRemoteHelper::sMozResponseAtom = 0;
|
|
Atom nsGtkMozRemoteHelper::sMozUserAtom = 0;
|
|
Atom nsGtkMozRemoteHelper::sMozProfileAtom = 0;
|
|
Atom nsGtkMozRemoteHelper::sMozProgramAtom = 0;
|
|
|
|
// XXX get this dynamically
|
|
static const char sRemoteVersion[] = "5.0";
|
|
|
|
void
|
|
nsGtkMozRemoteHelper::SetupVersion(GdkWindow *aWindow, const char *aProfile,
|
|
const char *aProgram)
|
|
{
|
|
Window window;
|
|
unsigned char *data = (unsigned char *)sRemoteVersion;
|
|
EnsureAtoms();
|
|
window = GDK_WINDOW_XWINDOW(aWindow);
|
|
|
|
// set our version
|
|
XChangeProperty(GDK_DISPLAY(), window, sMozVersionAtom, XA_STRING,
|
|
8, PropModeReplace, data, strlen(sRemoteVersion));
|
|
|
|
// get our username
|
|
char *logname;
|
|
logname = PR_GetEnv("LOGNAME");
|
|
if (logname) {
|
|
data = (unsigned char *)logname;
|
|
|
|
// set the property on the window if it's available
|
|
XChangeProperty(GDK_DISPLAY(), window, sMozUserAtom, XA_STRING,
|
|
8, PropModeReplace, data, strlen(logname));
|
|
}
|
|
|
|
// set our profile name and program name, if available.
|
|
if (aProfile) {
|
|
data = (unsigned char *)aProfile;
|
|
|
|
XChangeProperty(GDK_DISPLAY(), window, sMozProfileAtom, XA_STRING,
|
|
8, PropModeReplace, data, strlen(aProfile));
|
|
}
|
|
|
|
if (aProgram) {
|
|
data = (unsigned char *)aProgram;
|
|
|
|
XChangeProperty(GDK_DISPLAY(), window, sMozProgramAtom, XA_STRING,
|
|
8, PropModeReplace, data, strlen(aProgram));
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
nsGtkMozRemoteHelper::HandlePropertyChange(GtkWidget *aWidget,
|
|
GdkEventProperty *aEvent,
|
|
nsIWidget *ansIWidget)
|
|
{
|
|
|
|
EnsureAtoms();
|
|
|
|
// see if this is the command atom and it's new
|
|
if (aEvent->state == GDK_PROPERTY_NEW_VALUE &&
|
|
aEvent->window == aWidget->window &&
|
|
aEvent->atom == sMozCommandAtom)
|
|
{
|
|
int result;
|
|
Atom actual_type;
|
|
int actual_format;
|
|
unsigned long nitems, bytes_after;
|
|
char *data = 0;
|
|
|
|
result = XGetWindowProperty (GDK_DISPLAY(),
|
|
GDK_WINDOW_XWINDOW(aWidget->window),
|
|
sMozCommandAtom,
|
|
0, /* long_offset */
|
|
(65536 / sizeof (long)), /* long_length */
|
|
True, /* atomic delete after */
|
|
XA_STRING, /* req_type */
|
|
&actual_type, /* actual_type return */
|
|
&actual_format, /* actual_format_return */
|
|
&nitems, /* nitems_return */
|
|
&bytes_after, /* bytes_after_return */
|
|
(unsigned char **)&data); /* prop_return
|
|
( we only care about
|
|
the first ) */
|
|
if (result != Success)
|
|
{
|
|
// failed to get property off the window
|
|
return FALSE;
|
|
}
|
|
else if (!data || !*data)
|
|
{
|
|
// failed to get the data off the window or it was the wrong
|
|
// type
|
|
return FALSE;
|
|
}
|
|
// cool, we got the property data.
|
|
char *response = NULL;
|
|
// The reason that we are using a conditional free here is that if
|
|
// ParseCommand() fails below it's probably because of failed
|
|
// memory allocations. If that's the case we want to make sure
|
|
// that we try to get something back to the client instead of just
|
|
// giving up since a lot of clients will just hang forever. Hence
|
|
// using a static string.
|
|
PRBool freeResponse = PR_TRUE;
|
|
|
|
// parse the command
|
|
nsCOMPtr<nsIXRemoteService> remoteService;
|
|
remoteService = do_GetService(NS_IXREMOTESERVICE_CONTRACTID);
|
|
|
|
if (remoteService)
|
|
remoteService->ParseCommand(ansIWidget, data, &response);
|
|
|
|
if (!response)
|
|
{
|
|
response = "500 error parsing command";
|
|
freeResponse = PR_FALSE;
|
|
}
|
|
// put the property onto the window as the response
|
|
XChangeProperty (GDK_DISPLAY(), GDK_WINDOW_XWINDOW(aWidget->window),
|
|
sMozResponseAtom, XA_STRING,
|
|
8, PropModeReplace, (const unsigned char *)response, strlen (response));
|
|
if (freeResponse)
|
|
nsCRT::free(response);
|
|
XFree(data);
|
|
return TRUE;
|
|
}
|
|
else if (aEvent->state == GDK_PROPERTY_NEW_VALUE &&
|
|
aEvent->window == aWidget->window &&
|
|
aEvent->atom == sMozResponseAtom)
|
|
{
|
|
// client accepted the response. party on wayne.
|
|
return TRUE;
|
|
}
|
|
else if (aEvent->state == GDK_PROPERTY_NEW_VALUE &&
|
|
aEvent->window == aWidget->window &&
|
|
aEvent->atom == sMozLockAtom)
|
|
{
|
|
// someone locked the window
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
nsGtkMozRemoteHelper::EnsureAtoms(void)
|
|
{
|
|
// init our atoms if we need to
|
|
if (!sMozVersionAtom)
|
|
sMozVersionAtom = XInternAtom(GDK_DISPLAY(), MOZILLA_VERSION_PROP, False);
|
|
if (!sMozLockAtom)
|
|
sMozLockAtom = XInternAtom(GDK_DISPLAY(), MOZILLA_LOCK_PROP, False);
|
|
if (!sMozCommandAtom)
|
|
sMozCommandAtom = XInternAtom(GDK_DISPLAY(), MOZILLA_COMMAND_PROP, False);
|
|
if (!sMozResponseAtom)
|
|
sMozResponseAtom = XInternAtom(GDK_DISPLAY(), MOZILLA_RESPONSE_PROP,
|
|
False);
|
|
if (!sMozUserAtom)
|
|
sMozUserAtom = XInternAtom(GDK_DISPLAY(), MOZILLA_USER_PROP, False);
|
|
if (!sMozProfileAtom)
|
|
sMozProfileAtom = XInternAtom(GDK_DISPLAY(), MOZILLA_PROFILE_PROP, False);
|
|
if (!sMozProgramAtom)
|
|
sMozProgramAtom = XInternAtom(GDK_DISPLAY(), MOZILLA_PROGRAM_PROP, False);
|
|
|
|
}
|
|
|
|
|
|
nsGtkMozRemoteHelper::~nsGtkMozRemoteHelper()
|
|
{
|
|
}
|
|
|
|
nsGtkXRemoteWidgetHelper::nsGtkXRemoteWidgetHelper()
|
|
{
|
|
}
|
|
|
|
nsGtkXRemoteWidgetHelper::~nsGtkXRemoteWidgetHelper()
|
|
{
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS1(nsGtkXRemoteWidgetHelper, nsIXRemoteWidgetHelper)
|
|
|
|
NS_IMETHODIMP
|
|
nsGtkXRemoteWidgetHelper::EnableXRemoteCommands(nsIWidget *aWidget,
|
|
const char *aProfile,
|
|
const char *aProgram)
|
|
{
|
|
// find the native gdk window
|
|
GdkWindow *window = NS_STATIC_CAST(GdkWindow *,
|
|
aWidget->GetNativeData(NS_NATIVE_WINDOW));
|
|
if (!window)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// find the toplevel gdk window
|
|
GdkWindow *temp = window;
|
|
|
|
while (temp) {
|
|
temp = gdk_window_get_parent(window);
|
|
if (!temp || temp == GDK_ROOT_PARENT())
|
|
break;
|
|
window = temp;
|
|
}
|
|
|
|
// ok, found the toplevel window - set up the version information
|
|
nsGtkMozRemoteHelper::SetupVersion(window, aProfile, aProgram);
|
|
|
|
return NS_OK;
|
|
}
|
|
|