1024 lines
30 KiB
C
1024 lines
30 KiB
C
/* $Xorg: PProcess.c,v 1.6 2001/02/09 02:05:57 xorgcvs Exp $ */
|
|
/*
|
|
|
|
Copyright 1996, 1998 The Open Group
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
the above copyright notice appear in all copies and that both that
|
|
copyright notice and this permission notice appear in supporting
|
|
documentation.
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
|
ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABIL-
|
|
ITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of The Open Group shall
|
|
not be used in advertising or otherwise to promote the sale, use or
|
|
other dealings in this Software without prior written authorization from
|
|
The Open Group.
|
|
|
|
*/
|
|
/* $XFree86: xc/programs/xrx/plugin/PProcess.c,v 1.8 2004/04/03 22:38:55 tsi Exp $ */
|
|
|
|
#include "RxPlugin.h"
|
|
#include "XUrls.h"
|
|
#include "XAuth.h"
|
|
#include "XDpyName.h"
|
|
#include "Prefs.h"
|
|
#include <X11/StringDefs.h>
|
|
|
|
#include <limits.h> /* for MAXHOSTNAMELEN */
|
|
/* and in case we didn't get it from the headers above */
|
|
#ifndef MAXHOSTNAMELEN
|
|
# define MAXHOSTNAMELEN 256
|
|
#endif
|
|
|
|
#ifdef XUSE_XTREGISTERWINDOW
|
|
extern void _XtRegisterWindow (Window window, Widget widget);
|
|
#define XtRegisterDrawable(d,win,wid) _XtRegisterWindow(win,wid)
|
|
extern void _XtUnregisterWindow (Window window, Widget widget);
|
|
#define UnregisterDrawable(win,wid) _XtUnregisterWindow(win,wid)
|
|
#else
|
|
#define UnregisterDrawable(win,wid) XtUnregisterDrawable(XtDisplay(wid),win)
|
|
#endif
|
|
|
|
/* timeout for authorizations */
|
|
#define DEFAULT_TIMEOUT 300
|
|
#define NO_TIMEOUT 0
|
|
|
|
/***********************************************************************
|
|
* Try and do something sensible about window geometry
|
|
***********************************************************************/
|
|
static void
|
|
GetWindowGeometry(
|
|
Display* dpy,
|
|
Window win,
|
|
Position* x,
|
|
Position* y,
|
|
Dimension* width,
|
|
Dimension* height,
|
|
Dimension* border_width,
|
|
/* the following doesn't really belong here but it saves us from doing
|
|
another XGetWindowAttributes later on */
|
|
Colormap *cmap)
|
|
{
|
|
long mask;
|
|
XSizeHints* sizehints = XAllocSizeHints();
|
|
XWindowAttributes wattr;
|
|
|
|
if (XGetWindowAttributes (dpy, win, &wattr)) {
|
|
*x = wattr.x;
|
|
*y = wattr.y;
|
|
*width = wattr.width;
|
|
*height = wattr.height;
|
|
*border_width = wattr.border_width;
|
|
*cmap = wattr.colormap;
|
|
}
|
|
if (sizehints) {
|
|
XGetWMNormalHints (dpy, win, sizehints, &mask);
|
|
|
|
if (mask & (USPosition|PPosition)) {
|
|
*x = sizehints->x;
|
|
*y = sizehints->y;
|
|
*width = sizehints->width;
|
|
*height = sizehints->height;
|
|
XFree ((char*) sizehints);
|
|
return;
|
|
}
|
|
XFree ((char*) sizehints);
|
|
}
|
|
*x = 0;
|
|
*y = 0;
|
|
*width = 0;
|
|
*height = 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* a set of utility functions to manipulate Windows lists
|
|
***********************************************************************/
|
|
static Bool
|
|
IsInWinList(Window *list, int count, Window win)
|
|
{
|
|
int i;
|
|
for (i = 0; i < count; i++, list++)
|
|
if (*list == win)
|
|
return True;
|
|
return False;
|
|
}
|
|
|
|
#ifdef UNUSED
|
|
static void
|
|
AppendToWinList(Window **new_list, int *new_count,
|
|
Window *list, int count, Window win)
|
|
{
|
|
*new_count = count + 1;
|
|
*new_list = (Window*) malloc(sizeof(Window) * *new_count);
|
|
memcpy(*new_list, list, sizeof(Window) * count);
|
|
(*new_list)[count] = win;
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
PrependToWinList(Window **new_list, int *new_count,
|
|
Window *list, int count, Window win)
|
|
{
|
|
*new_count = count + 1;
|
|
*new_list = (Window*) malloc(sizeof(Window) * *new_count);
|
|
(*new_list)[0] = win;
|
|
memcpy(*new_list + 1, list, sizeof(Window) * count);
|
|
}
|
|
|
|
/* rotate the list so the given window is at the beginning of it */
|
|
static void
|
|
SetFirstWinList(Window *list, int count, Window win)
|
|
{
|
|
int i;
|
|
|
|
/* look for the given window starting from the end */
|
|
list += count - 1;
|
|
for (i = 0; i < count; i++, list--)
|
|
if (*list == win)
|
|
break;
|
|
if (i < count) { /* when we found it rotate from there */
|
|
/* shift every element to the right */
|
|
for (i++; i < count; i++) {
|
|
list--;
|
|
list[1] = list[0];
|
|
}
|
|
/* and set the first one */
|
|
*list = win;
|
|
}
|
|
}
|
|
|
|
/* rotate the list so the given window which should be the first item is
|
|
at the end of it */
|
|
static void
|
|
SetLastWinList(Window *list, int count, Window win)
|
|
{
|
|
if (*list == win) {
|
|
int i;
|
|
/* shift every element to the left */
|
|
for (i = 0; i < count - 1; i++, list++)
|
|
list[0] = list[1];
|
|
/* and set the last one */
|
|
*list = win;
|
|
}
|
|
}
|
|
|
|
static void
|
|
RemoveFromWinList(Window **wlist, int *count, Window win)
|
|
{
|
|
Window *list = *wlist;
|
|
int i;
|
|
/* look for the window to remove */
|
|
for (i = 0; i < *count; i++, list++)
|
|
if (*list == win) {
|
|
(*count)--;
|
|
break;
|
|
}
|
|
/* then simply shift following elements to the left */
|
|
for (; i < *count; i++, list++)
|
|
list[0] = list[1];
|
|
}
|
|
|
|
#ifdef UNUSED
|
|
static void
|
|
ConcatWinLists(Window **list, int *count,
|
|
Window *list1, int count1,
|
|
Window *list2, int count2)
|
|
{
|
|
*count = count1 + count2;
|
|
*list = (Window*) malloc(sizeof(Window) * *count);
|
|
memcpy(*list, list1, sizeof(Window) * count1);
|
|
memcpy(*list + count1, list2, sizeof(Window) * count2);
|
|
}
|
|
|
|
static void
|
|
SubstractWinLists(Window **wlist, int *count,
|
|
Window *list1, int count1)
|
|
{
|
|
Window *list = *wlist;
|
|
int i, j;
|
|
/* look for the beginning of the list to remove */
|
|
for (i = 0; i < *count; i++, list++)
|
|
if (*list == *list1)
|
|
break;
|
|
/* skip the list to remove stopping at the end of one of the lists
|
|
or at the first alien element */
|
|
for (j = 0; j < count1 && i + j < *count; j++, list1++)
|
|
if (list[j] != *list1)
|
|
break;
|
|
/* then shift following elements */
|
|
*count -= j;
|
|
for (; i < *count; i++, list++)
|
|
list[0] = list[j];
|
|
}
|
|
#endif
|
|
|
|
/***********************************************************************
|
|
* Add window to the WM_COLORMAP_WINDOWS property on the Netscape
|
|
* toplevel widget if necessary
|
|
***********************************************************************/
|
|
static void
|
|
SetWMColormap(PluginInstance* This, Window win)
|
|
{
|
|
int i;
|
|
Colormap top_cmap;
|
|
Arg arg;
|
|
|
|
/* get window's record */
|
|
for (i = 0; i < This->nclient_windows; i++)
|
|
if ((This->client_windows[i].win = win))
|
|
break;
|
|
|
|
if (i == This->nclient_windows)
|
|
return;
|
|
|
|
/* if window's colormap is different from toplevel's one set property */
|
|
XtSetArg(arg, XtNcolormap, &top_cmap);
|
|
XtGetValues(This->toplevel_widget, &arg, 1);
|
|
if (This->client_windows[i].colormap != top_cmap) {
|
|
Window *cur_list;
|
|
int cur_count = 0;
|
|
|
|
/* if there is already a non empty list we need to update it */
|
|
if (XGetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget),
|
|
&cur_list, &cur_count) == True &&
|
|
cur_count != 0) {
|
|
|
|
if (IsInWinList(cur_list, cur_count, win)) {
|
|
/* window is already in the list just move it in first place */
|
|
SetFirstWinList(cur_list, cur_count, win);
|
|
XSetWMColormapWindows(RxGlobal.dpy,
|
|
XtWindow(This->toplevel_widget),
|
|
cur_list, cur_count);
|
|
} else {
|
|
/* window is not in the list add it in first place */
|
|
Window *new_list;
|
|
int new_count;
|
|
|
|
PrependToWinList(&new_list, &new_count,
|
|
cur_list, cur_count, win);
|
|
XSetWMColormapWindows(RxGlobal.dpy,
|
|
XtWindow(This->toplevel_widget),
|
|
new_list, new_count);
|
|
free(new_list);
|
|
}
|
|
} else { /* no list yet so lets make one */
|
|
Window list[2];
|
|
|
|
list[0] = win;
|
|
list[1] = XtWindow(This->toplevel_widget);
|
|
XSetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget),
|
|
list, 2);
|
|
}
|
|
if (cur_count != 0)
|
|
XFree(cur_list);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Move window at the end of the WM_COLORMAP_WINDOWS property list on
|
|
* the Netscape toplevel widget
|
|
***********************************************************************/
|
|
static void
|
|
UnsetWMColormap(PluginInstance* This, Window win)
|
|
{
|
|
Window *list;
|
|
int count = 0;
|
|
|
|
if (XGetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget),
|
|
&list, &count) == True && count != 0) {
|
|
SetLastWinList(list, count, win);
|
|
XSetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget),
|
|
list, count);
|
|
}
|
|
if (count != 0)
|
|
XFree(list);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Remove window from the WM_COLORMAP_WINDOWS property on the Netscape
|
|
* toplevel widget
|
|
***********************************************************************/
|
|
static void
|
|
ResetWMColormap(PluginInstance* This, Window win)
|
|
{
|
|
Window *list;
|
|
int count = 0;
|
|
|
|
if (XGetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget),
|
|
&list, &count) == True && count != 0) {
|
|
RemoveFromWinList(&list, &count, win);
|
|
|
|
if (count > 1)
|
|
XSetWMColormapWindows(RxGlobal.dpy, XtWindow(This->toplevel_widget),
|
|
list, count);
|
|
else { /* remove list when it becomes useless */
|
|
Atom prop;
|
|
|
|
prop = XInternAtom (RxGlobal.dpy, "WM_COLORMAP_WINDOWS", False);
|
|
XDeleteProperty(RxGlobal.dpy, XtWindow(This->toplevel_widget), prop);
|
|
}
|
|
}
|
|
if (count != 0)
|
|
XFree(list);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Event Handler to reparent client window under plugin window
|
|
***********************************************************************/
|
|
static
|
|
void
|
|
SubstructureRedirectHandler (
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent* event,
|
|
Boolean* cont)
|
|
{
|
|
windowrec* new_list;
|
|
PluginInstance* This = (PluginInstance*) client_data;
|
|
|
|
#ifdef PLUGIN_TRACE
|
|
fprintf (stderr, "%s\n", "SubstructureRedirectHandler");
|
|
fprintf (stderr, "This: 0x%x\n", This);
|
|
#endif
|
|
|
|
switch (event->type) {
|
|
case ConfigureRequest:
|
|
{
|
|
XWindowChanges config;
|
|
config.x = event->xconfigurerequest.x;
|
|
config.y = event->xconfigurerequest.y;
|
|
config.width = event->xconfigurerequest.width;
|
|
config.height = event->xconfigurerequest.height;
|
|
config.border_width = event->xconfigurerequest.border_width;
|
|
config.sibling = event->xconfigurerequest.above;
|
|
config.stack_mode = event->xconfigurerequest.detail;
|
|
#if 0
|
|
fprintf (stderr, "configuring at %dx%d+%d+%d\n",
|
|
config.width, config.height, config.x, config.y);
|
|
#endif
|
|
XConfigureWindow (RxGlobal.dpy,
|
|
event->xconfigurerequest.window,
|
|
event->xconfigurerequest.value_mask,
|
|
&config);
|
|
}
|
|
break;
|
|
|
|
case MapRequest:
|
|
|
|
RxpSetStatusWidget(This, RUNNING);
|
|
|
|
{
|
|
Window for_win;
|
|
int i;
|
|
|
|
if (XGetTransientForHint (RxGlobal.dpy, event->xmaprequest.window,
|
|
&for_win)) {
|
|
for (i = 0; i < This->nclient_windows; i++)
|
|
if (for_win == This->client_windows[i].win)
|
|
XMapWindow (RxGlobal.dpy, event->xmaprequest.window);
|
|
return;
|
|
}
|
|
}
|
|
new_list = (windowrec*)
|
|
NPN_MemAlloc (sizeof (windowrec) * (This->nclient_windows + 1));
|
|
if (new_list) {
|
|
Position x, y;
|
|
Dimension width, height;
|
|
Dimension border_width;
|
|
Colormap cmap;
|
|
int n;
|
|
Atom* wm_proto;
|
|
windowrec* wp;
|
|
Window destwin = XtWindow (This->plugin_widget);
|
|
|
|
This->nclient_windows++;
|
|
if (This->nclient_windows > 1)
|
|
memcpy ((void*) new_list, (void*) This->client_windows,
|
|
(This->nclient_windows - 1) * sizeof (windowrec));
|
|
if (This->client_windows)
|
|
NPN_MemFree (This->client_windows);
|
|
This->client_windows = new_list;
|
|
|
|
x = y = 0;
|
|
width = height = border_width = 0;
|
|
GetWindowGeometry (RxGlobal.dpy, event->xmaprequest.window,
|
|
&x, &y, &width, &height, &border_width, &cmap);
|
|
|
|
wp = &This->client_windows[This->nclient_windows - 1];
|
|
wp->win = event->xmaprequest.window;
|
|
wp->x = x; wp->y = y;
|
|
wp->width = width; wp->height = height;
|
|
wp->border_width = border_width;
|
|
wp->flags = RxpMapped;
|
|
wp->colormap = cmap;
|
|
|
|
if (XGetWMProtocols (RxGlobal.dpy, wp->win, &wm_proto, &n)) {
|
|
int i;
|
|
Atom* ap;
|
|
|
|
for (i = 0, ap = wm_proto; i < n; i++, ap++) {
|
|
if (*ap == RxGlobal.wm_delete_window)
|
|
wp->flags |= RxpWmDelWin;
|
|
}
|
|
if (wm_proto) XFree ((char*) wm_proto);
|
|
}
|
|
|
|
XSelectInput(RxGlobal.dpy, wp->win,
|
|
EnterWindowMask | LeaveWindowMask);
|
|
XtRegisterDrawable (RxGlobal.dpy, wp->win, This->plugin_widget);
|
|
XReparentWindow (RxGlobal.dpy, wp->win, destwin, wp->x, wp->y);
|
|
XMapWindow (RxGlobal.dpy, wp->win);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Event Handler to forward WM_DELETE_WINDOW events to the client windows
|
|
***********************************************************************/
|
|
void
|
|
RxpWmDelWinHandler (
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent* event,
|
|
Boolean* cont)
|
|
{
|
|
PluginInstance* This = (PluginInstance*) client_data;
|
|
int i;
|
|
|
|
if (event == NULL ||
|
|
(event->type == ClientMessage &&
|
|
event->xclient.message_type == RxGlobal.wm_protocols &&
|
|
event->xclient.data.l[0] == RxGlobal.wm_delete_window)) {
|
|
for (i = 0; i < This->nclient_windows; i++) {
|
|
if (This->client_windows[i].flags & RxpWmDelWin) {
|
|
XClientMessageEvent ev;
|
|
|
|
ev.type = ClientMessage;
|
|
ev.window = This->client_windows[i].win;
|
|
ev.message_type = RxGlobal.wm_protocols;
|
|
ev.format = 32;
|
|
ev.data.l[0] = RxGlobal.wm_delete_window;
|
|
ev.data.l[1] = XtLastTimestampProcessed (XtDisplay (widget));
|
|
XSendEvent (RxGlobal.dpy, ev.window, FALSE, 0L, (XEvent*) &ev);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Event Handler to forward ConfigureNotify events to the client windows
|
|
***********************************************************************/
|
|
static void
|
|
StructureNotifyHandler (
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent* event,
|
|
Boolean* cont)
|
|
{
|
|
PluginInstance* This = (PluginInstance*) client_data;
|
|
|
|
#ifdef PLUGIN_TRACE
|
|
fprintf (stderr, "%s\n", "StructureNotifyHandler");
|
|
#endif
|
|
|
|
switch (event->type) {
|
|
|
|
/*
|
|
* For the testplugin, which uses a ScrolledWindow, the clipped
|
|
* window, i.e. This->plugin, is "configured" when the user pans
|
|
* around the ScrolledWindow. The Netscape scrolled-window is
|
|
* different. It moves-and-resizes the clip window, causing the
|
|
* child, i.e. This->plugin, to be "dragged" up by win-gravity.
|
|
*/
|
|
case ConfigureNotify:
|
|
case GravityNotify:
|
|
if (This->plugin_widget == NULL)
|
|
return;
|
|
|
|
{
|
|
int i;
|
|
Position x, y;
|
|
XConfigureEvent sendev;
|
|
|
|
XtTranslateCoords (This->plugin_widget, 0, 0, &x, &y);
|
|
for (i = 0; i < This->nclient_windows; i++) {
|
|
sendev.type = ConfigureNotify;
|
|
sendev.send_event = True;
|
|
sendev.event = sendev.window = This->client_windows[i].win;
|
|
sendev.x = x + This->client_windows[i].x;
|
|
sendev.y = y + This->client_windows[i].y;
|
|
sendev.width = This->client_windows[i].width;
|
|
sendev.height = This->client_windows[i].height;
|
|
sendev.border_width = This->client_windows[i].border_width;
|
|
sendev.above = None;
|
|
sendev.override_redirect = False;
|
|
if (!XSendEvent (RxGlobal.dpy, This->client_windows[i].win,
|
|
False, StructureNotifyMask,
|
|
(XEvent*) &sendev))
|
|
(void) fprintf (stderr, "%s\n", "XSendEvent Failed");
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Event Handler to detect the destruction of a client window
|
|
***********************************************************************/
|
|
static void
|
|
SubstructureNotifyHandler (
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent* event,
|
|
Boolean* cont)
|
|
{
|
|
PluginInstance* This = (PluginInstance*) client_data;
|
|
|
|
#ifdef PLUGIN_TRACE
|
|
fprintf (stderr, "%s\n", "SubstructureNotifyHandler");
|
|
#endif
|
|
|
|
if (event->type == DestroyNotify) {
|
|
int i;
|
|
#ifdef PLUGIN_TRACE
|
|
fprintf (stderr, "%s\n", "DestroyNotify");
|
|
#endif
|
|
for (i = 0; i < This->nclient_windows; i++)
|
|
if (This->client_windows[i].win == event->xdestroywindow.window) {
|
|
This->nclient_windows--;
|
|
if (This->nclient_windows > 0) {
|
|
/* remove this window from the list */
|
|
for (; i < This->nclient_windows; i++)
|
|
This->client_windows[i] = This->client_windows[i + 1];
|
|
} else { /* no more client windows! */
|
|
/* get back to user to restart the application */
|
|
RxpSetStatusWidget(This, WAITING);
|
|
}
|
|
ResetWMColormap(This, event->xdestroywindow.window);
|
|
UnregisterDrawable(event->xdestroywindow.window,
|
|
This->plugin_widget);
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Arrange to receive (synthetic) ConfigureNotify events on the proper
|
|
* windows of this instance and relay them to the embedded apps
|
|
***********************************************************************/
|
|
static void
|
|
SetupStructureNotify (PluginInstance* This)
|
|
{
|
|
/* Get ConfigureNotify when the browser is moved */
|
|
XtAddRawEventHandler (This->toplevel_widget,
|
|
StructureNotifyMask,
|
|
False,
|
|
StructureNotifyHandler,
|
|
(XtPointer) This);
|
|
|
|
XtAddRawEventHandler (This->toplevel_widget,
|
|
NoEventMask,
|
|
True,
|
|
RxpWmDelWinHandler,
|
|
(XtPointer) This);
|
|
#if 0
|
|
XmAddWMProtocolCallback (This->toplevel_widget,
|
|
RxGlobal.wm_delete_window,
|
|
RxpWmDelWinHandler,
|
|
(XtPointer) This);
|
|
#endif
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Event Handler to deal with colormap settings
|
|
***********************************************************************/
|
|
static void
|
|
CrossingHandler (
|
|
Widget widget,
|
|
XtPointer client_data,
|
|
XEvent* event,
|
|
Boolean* cont)
|
|
{
|
|
PluginInstance* This = (PluginInstance*) client_data;
|
|
|
|
#ifdef PLUGIN_TRACE
|
|
fprintf (stderr, "%s: 0x%x\n", "CrossingHandler", event->xany.window);
|
|
#endif
|
|
|
|
if (event->xany.window != XtWindow(This->plugin_widget) &&
|
|
event->xcrossing.detail != NotifyInferior) {
|
|
if (event->type == EnterNotify) {
|
|
#ifdef PLUGIN_TRACE
|
|
fprintf (stderr, "%s\n", "EnterNotify");
|
|
#endif
|
|
SetWMColormap(This, event->xany.window);
|
|
} else if (event->type == LeaveNotify) {
|
|
#ifdef PLUGIN_TRACE
|
|
fprintf (stderr, "%s\n", "LeaveNotify");
|
|
#endif
|
|
UnsetWMColormap(This, event->xany.window);
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Setup various event handlers on the plugin widget
|
|
***********************************************************************/
|
|
void
|
|
RxpSetupPluginEventHandlers (PluginInstance* This)
|
|
{
|
|
int i;
|
|
|
|
/* Get ConfigureNotify and GravityNotify on the plugin */
|
|
XtAddEventHandler (This->plugin_widget,
|
|
StructureNotifyMask,
|
|
False,
|
|
StructureNotifyHandler,
|
|
(XtPointer) This);
|
|
/* Arrange to receive DestroyNotify events on the clients windows. */
|
|
XtAddEventHandler (This->plugin_widget,
|
|
SubstructureNotifyMask,
|
|
False,
|
|
SubstructureNotifyHandler,
|
|
(XtPointer) This);
|
|
/* Arrange to receive MapRequest and ConfigureRequest events on the
|
|
* netscape plug-in widget. */
|
|
XtAddRawEventHandler(This->plugin_widget,
|
|
SubstructureRedirectMask,
|
|
False,
|
|
SubstructureRedirectHandler,
|
|
(XtPointer) This);
|
|
XtRegisterDrawable (RxGlobal.dpy, This->app_group, This->plugin_widget);
|
|
|
|
/* Arrange to receive Enter and Leave Notify events on application's
|
|
toplevel windows */
|
|
XtAddRawEventHandler(This->plugin_widget,
|
|
EnterWindowMask | LeaveWindowMask,
|
|
False,
|
|
CrossingHandler,
|
|
(XtPointer) This);
|
|
for (i = 0; i < This->nclient_windows; i++) {
|
|
XtRegisterDrawable (RxGlobal.dpy,
|
|
This->client_windows[i].win, This->plugin_widget);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* The instance is gone. Remove Event Handlers so that they aren't
|
|
* called with a reference to the old instance.
|
|
***********************************************************************/
|
|
void
|
|
RxpTeardown (PluginInstance* This)
|
|
{
|
|
if (This->toplevel_widget != NULL) {
|
|
/* ConfigureNotify on top level */
|
|
XtRemoveRawEventHandler (This->toplevel_widget,
|
|
StructureNotifyMask,
|
|
False,
|
|
StructureNotifyHandler,
|
|
(XtPointer) This);
|
|
XtRemoveRawEventHandler (This->toplevel_widget,
|
|
NoEventMask,
|
|
True,
|
|
RxpWmDelWinHandler,
|
|
(XtPointer) This);
|
|
#if 0
|
|
XmRemoveWMProtocolCallback (This->toplevel_widget,
|
|
RxGlobal.wm_delete_window,
|
|
RxpWmDelWinHandler,
|
|
(XtPointer) This);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Process the given RxParams and make the RxReturnParams
|
|
***********************************************************************/
|
|
|
|
static int
|
|
ProcessUIParams(PluginInstance* This,
|
|
Boolean trusted, Boolean use_fwp, Boolean use_lbx,
|
|
RxParams *in, RxReturnParams *out, char **x_ui_auth_ret)
|
|
{
|
|
XSecurityAuthorization dum;
|
|
int dummy;
|
|
char *display_name;
|
|
|
|
This->app_group = None;
|
|
if (out->embedded != RxFalse) { /* default is embedded */
|
|
/* let's see whether the server supports AppGroups or not */
|
|
if (RxGlobal.has_appgroup == RxUndef) {
|
|
if (XQueryExtension(RxGlobal.dpy, "XC-APPGROUP",
|
|
&dummy, &dummy, &dummy) &&
|
|
XagQueryVersion (RxGlobal.dpy, &dummy, &dummy))
|
|
RxGlobal.has_appgroup = RxTrue;
|
|
else
|
|
RxGlobal.has_appgroup = RxFalse;
|
|
}
|
|
if (RxGlobal.has_appgroup == RxTrue) {
|
|
Screen *scr;
|
|
Colormap cmap;
|
|
Arg arg;
|
|
|
|
/* use plugin's colormap as the default colormap */
|
|
XtSetArg(arg, XtNcolormap, &cmap);
|
|
XtGetValues(This->plugin_widget, &arg, 1);
|
|
scr = XtScreen(This->plugin_widget);
|
|
if (cmap == DefaultColormapOfScreen(scr)) {
|
|
XagCreateEmbeddedApplicationGroup (RxGlobal.dpy, None,
|
|
cmap,
|
|
BlackPixelOfScreen(scr),
|
|
WhitePixelOfScreen(scr),
|
|
&This->app_group);
|
|
} else {
|
|
XColor black, white;
|
|
Pixel pixels[2];
|
|
|
|
black.red = black.green = black.blue = 0;
|
|
XAllocColor(RxGlobal.dpy, cmap, &black);
|
|
white.red = white.green = white.blue = 65535;
|
|
XAllocColor(RxGlobal.dpy, cmap, &white);
|
|
XagCreateEmbeddedApplicationGroup (RxGlobal.dpy, None,
|
|
cmap,
|
|
pixels[0] = black.pixel,
|
|
pixels[1] = white.pixel,
|
|
&This->app_group);
|
|
XFreeColors(RxGlobal.dpy, cmap, pixels, 2, 0);
|
|
}
|
|
SetupStructureNotify (This);
|
|
RxpSetupPluginEventHandlers (This);
|
|
} else { /* too bad */
|
|
out->embedded = RxFalse;
|
|
fprintf(stderr, "Warning: Cannot perform embedding as \
|
|
requested, APPGROUP extension not supported\n");
|
|
}
|
|
}
|
|
|
|
if (in->x_ui_auth[0] != 0) {
|
|
GetXAuth(RxGlobal.dpy, in->x_ui_auth[0], in->x_ui_auth_data[0],
|
|
trusted, This->app_group, False, DEFAULT_TIMEOUT,
|
|
x_ui_auth_ret, &This->x_ui_auth_id, &dummy);
|
|
} else if (in->x_auth[0] != 0)
|
|
GetXAuth(RxGlobal.dpy, in->x_auth[0], in->x_auth_data[0],
|
|
trusted, This->app_group, False, DEFAULT_TIMEOUT,
|
|
x_ui_auth_ret, &This->x_ui_auth_id, &dummy);
|
|
|
|
/* make sure we use the server the user wants us to use */
|
|
if (RxGlobal.has_real_server == RxUndef) {
|
|
Display *rdpy = RxGlobal.dpy;
|
|
char *real_display = getenv("XREALDISPLAY");
|
|
RxGlobal.has_real_server = RxFalse;
|
|
if (real_display != NULL) {
|
|
rdpy = XOpenDisplay(real_display);
|
|
if (rdpy == NULL)
|
|
rdpy = RxGlobal.dpy;
|
|
else
|
|
RxGlobal.has_real_server = RxTrue;
|
|
}
|
|
/* let's see now whether the server supports LBX or not */
|
|
if (XQueryExtension(rdpy, "LBX", &dummy, &dummy, &dummy))
|
|
RxGlobal.has_ui_lbx = RxTrue;
|
|
else
|
|
RxGlobal.has_ui_lbx = RxFalse;
|
|
|
|
if (rdpy != RxGlobal.dpy)
|
|
XCloseDisplay(rdpy);
|
|
}
|
|
if (RxGlobal.has_real_server == RxTrue)
|
|
display_name = getenv("XREALDISPLAY");
|
|
else
|
|
display_name = DisplayString(RxGlobal.dpy);
|
|
|
|
/* let's see whether we have a firewall proxy */
|
|
if (use_fwp == True && RxGlobal.has_ui_fwp == RxUndef) {
|
|
RxGlobal.fwp_dpyname = GetXFwpDisplayName(display_name);
|
|
if (RxGlobal.fwp_dpyname != NULL)
|
|
RxGlobal.has_ui_fwp = RxTrue;
|
|
else {
|
|
/*
|
|
* We were supposed to use the firewall proxy but we
|
|
* couldn't get a connection. There is no need to
|
|
* continue.
|
|
*/
|
|
return 1;
|
|
}
|
|
}
|
|
if (use_fwp == True && RxGlobal.has_ui_fwp == RxTrue)
|
|
out->ui = GetXUrl(RxGlobal.fwp_dpyname, *x_ui_auth_ret, in->action);
|
|
else
|
|
out->ui = GetXUrl(display_name, *x_ui_auth_ret, in->action);
|
|
|
|
if (in->x_ui_lbx == RxTrue) {
|
|
if (use_lbx == True) {
|
|
if (RxGlobal.has_ui_lbx == RxTrue) {
|
|
out->x_ui_lbx = RxTrue;
|
|
|
|
/* let's get a key for the proxy now */
|
|
if (in->x_ui_lbx_auth[0] != 0) {
|
|
GetXAuth(RxGlobal.dpy, in->x_ui_lbx_auth[0],
|
|
in->x_ui_lbx_auth_data[0],
|
|
trusted, None, False, DEFAULT_TIMEOUT,
|
|
&out->x_ui_lbx_auth, &dum, &dummy);
|
|
} else if (in->x_auth[0] != 0)
|
|
GetXAuth(RxGlobal.dpy, in->x_auth[0], in->x_auth_data[0],
|
|
trusted, None, False, DEFAULT_TIMEOUT,
|
|
&out->x_ui_lbx_auth, &dum, &dummy);
|
|
} else {
|
|
out->x_ui_lbx = RxFalse;
|
|
fprintf(stderr, "Warning: Cannot setup LBX as requested, \
|
|
LBX extension not supported\n");
|
|
}
|
|
} else
|
|
out->x_ui_lbx = RxFalse;
|
|
} else /* it's either RxFalse or RxUndef */
|
|
out->x_ui_lbx = in->x_ui_lbx;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
ProcessPrintParams(PluginInstance* This,
|
|
Boolean trusted, Boolean use_fwp, Boolean use_lbx,
|
|
RxParams *in, RxReturnParams *out, char *x_ui_auth)
|
|
{
|
|
char *auth = NULL;
|
|
XSecurityAuthorization dum;
|
|
int dummy;
|
|
|
|
/* let's find out if we have a print server */
|
|
if (RxGlobal.has_printer == RxUndef) {
|
|
RxGlobal.pdpy_name = GetXPrintDisplayName(&RxGlobal.printer_name);
|
|
if (RxGlobal.pdpy_name != NULL) {
|
|
/* open connection to the print server */
|
|
RxGlobal.pdpy = XOpenDisplay(RxGlobal.pdpy_name);
|
|
if (RxGlobal.pdpy != NULL)
|
|
RxGlobal.has_printer = RxTrue;
|
|
else
|
|
RxGlobal.has_printer = RxFalse;
|
|
} else {
|
|
/* no server specified,
|
|
let's see if the video server could do it */
|
|
if (XQueryExtension(RxGlobal.dpy, "XpExtension",
|
|
&dummy, &dummy, &dummy)) {
|
|
RxGlobal.has_printer = RxTrue;
|
|
RxGlobal.pdpy = RxGlobal.dpy;
|
|
} else
|
|
RxGlobal.has_printer = RxFalse;
|
|
}
|
|
}
|
|
if (RxGlobal.has_printer == RxFalse) {
|
|
fprintf(stderr, "Warning: Cannot setup X printer as requested, \
|
|
no server found\n");
|
|
return 0;
|
|
}
|
|
|
|
/* create a key only when the video server is not the print
|
|
server or when we didn't create a key yet */
|
|
if (RxGlobal.pdpy != RxGlobal.dpy || x_ui_auth == NULL) {
|
|
if (in->x_print_auth[0] != 0)
|
|
GetXAuth(RxGlobal.pdpy, in->x_print_auth[0],
|
|
in->x_print_auth_data[0],
|
|
trusted, None, False, NO_TIMEOUT,
|
|
&auth, &This->x_print_auth_id, &dummy);
|
|
else if (in->x_auth[0] != 0)
|
|
GetXAuth(RxGlobal.pdpy, in->x_auth[0], in->x_auth_data[0],
|
|
trusted, None, False, NO_TIMEOUT,
|
|
&auth, &This->x_print_auth_id, &dummy);
|
|
}
|
|
|
|
/* let's see whether we have a firewall proxy */
|
|
if (use_fwp == True && RxGlobal.has_print_fwp == RxUndef) {
|
|
RxGlobal.pfwp_dpyname = GetXFwpDisplayName(DisplayString(RxGlobal.pdpy));
|
|
if (RxGlobal.pfwp_dpyname != NULL)
|
|
RxGlobal.has_print_fwp = RxTrue;
|
|
else {
|
|
/*
|
|
* We were supposed to use the firewall proxy but we
|
|
* couldn't get a connection. There is no need to
|
|
* continue.
|
|
*/
|
|
return 1;
|
|
}
|
|
}
|
|
if (use_fwp == True && RxGlobal.has_print_fwp == RxTrue)
|
|
out->print = GetXPrintUrl(RxGlobal.pfwp_dpyname,
|
|
RxGlobal.printer_name, auth,
|
|
in->action);
|
|
else
|
|
out->print = GetXPrintUrl(DisplayString(RxGlobal.pdpy),
|
|
RxGlobal.printer_name, auth,
|
|
in->action);
|
|
|
|
if (auth != NULL)
|
|
NPN_MemFree(auth);
|
|
|
|
if (in->x_print_lbx == RxTrue) {
|
|
if (use_lbx == True) {
|
|
/* let's see whether the server supports LBX or not */
|
|
if (RxGlobal.has_print_lbx == RxUndef) {
|
|
if (RxGlobal.pdpy == RxGlobal.dpy &&
|
|
RxGlobal.has_ui_lbx != RxUndef) {
|
|
/* the video server is the print server and we already
|
|
know whether it supports LBX or not */
|
|
RxGlobal.has_print_lbx = RxGlobal.has_ui_lbx;
|
|
} else {
|
|
if (XQueryExtension(RxGlobal.pdpy, "LBX",
|
|
&dummy, &dummy, &dummy))
|
|
RxGlobal.has_print_lbx = RxTrue;
|
|
else
|
|
RxGlobal.has_print_lbx = RxFalse;
|
|
}
|
|
}
|
|
if (RxGlobal.has_print_lbx == RxTrue) {
|
|
out->x_print_lbx = RxTrue;
|
|
if (RxGlobal.pdpy != RxGlobal.dpy) {
|
|
/* let's get a key for the proxy now */
|
|
if (in->x_print_lbx_auth[0] != 0) {
|
|
GetXAuth(RxGlobal.pdpy, in->x_print_lbx_auth[0],
|
|
in->x_print_lbx_auth_data[0],
|
|
trusted, None, False, DEFAULT_TIMEOUT,
|
|
&out->x_print_lbx_auth, &dum, &dummy);
|
|
} else if (in->x_auth[0] != 0)
|
|
GetXAuth(RxGlobal.pdpy, in->x_auth[0],
|
|
in->x_auth_data[0],
|
|
trusted, None, False, DEFAULT_TIMEOUT,
|
|
&out->x_print_lbx_auth, &dum, &dummy);
|
|
}
|
|
} else {
|
|
out->x_print_lbx = RxFalse;
|
|
fprintf(stderr, "Warning: Cannot setup LBX as \
|
|
requested, LBX extension not supported\n");
|
|
}
|
|
} else
|
|
out->x_print_lbx = RxFalse;
|
|
} else /* it's either RxFalse or RxUndef */
|
|
out->x_print_lbx = in->x_print_lbx;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
RxpProcessParams(PluginInstance* This, RxParams *in, RxReturnParams *out)
|
|
{
|
|
char *x_ui_auth = NULL;
|
|
char webserver[MAXHOSTNAMELEN];
|
|
Boolean trusted, use_fwp, use_lbx;
|
|
int return_value = 0;
|
|
|
|
#ifdef PLUGIN_TRACE
|
|
fprintf (stderr, "%s\n", "RxpProcessParams");
|
|
fprintf (stderr, "This: 0x%x\n", This);
|
|
#endif
|
|
|
|
/* init return struture */
|
|
memset(out, 0, sizeof(RxReturnParams));
|
|
out->x_ui_lbx = RxUndef;
|
|
out->x_print_lbx = RxUndef;
|
|
out->action = in->action;
|
|
|
|
if (in->embedded != RxUndef)
|
|
out->embedded = in->embedded;
|
|
else
|
|
out->embedded = RxUndef;
|
|
|
|
out->width = in->width;
|
|
out->height = in->height;
|
|
|
|
if (RxGlobal.get_prefs == True) {
|
|
GetPreferences(This->toplevel_widget, &RxGlobal.prefs);
|
|
RxGlobal.get_prefs = False;
|
|
}
|
|
ComputePreferences(&RxGlobal.prefs,
|
|
ParseHostname(in->action, webserver, MAXHOSTNAMELEN) ? webserver : NULL,
|
|
&trusted, &use_fwp, &use_lbx);
|
|
|
|
if (in->ui[0] == XUI) /* X display needed */
|
|
return_value = ProcessUIParams(This, trusted, use_fwp, use_lbx,
|
|
in, out, &x_ui_auth);
|
|
|
|
if (in->print[0] == XPrint) /* XPrint server needed */
|
|
return_value = ProcessPrintParams(This, trusted, use_fwp, use_lbx,
|
|
in, out, x_ui_auth);
|
|
|
|
if (x_ui_auth != NULL)
|
|
NPN_MemFree(x_ui_auth);
|
|
|
|
return return_value;
|
|
}
|