aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/hw/nxagent/Screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/hw/nxagent/Screen.c')
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Screen.c4230
1 files changed, 4230 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Screen.c b/nx-X11/programs/Xserver/hw/nxagent/Screen.c
new file mode 100644
index 000000000..b847b08e6
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Screen.c
@@ -0,0 +1,4230 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of NoMachine. Redistribution and use of the present */
+/* software is allowed according to terms specified in the file LICENSE */
+/* which comes in the source distribution. */
+/* */
+/* Check http://www.nomachine.com/licensing.html for applicability. */
+/* */
+/* NX and NoMachine are trademarks of Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+/*
+ * Used by the auto-disconnect feature.
+ */
+
+#include <signal.h>
+
+#include "scrnintstr.h"
+#include "dix.h"
+#include "dixstruct.h"
+#include "mi.h"
+#include "micmap.h"
+#include "colormapst.h"
+#include "resource.h"
+#include "mipointer.h"
+#include "../../fb/fb.h"
+#include "../../randr/randrstr.h"
+#include "inputstr.h"
+#include "mivalidate.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Extensions.h"
+#include "Atoms.h"
+#include "GCs.h"
+#include "GCOps.h"
+#include "Image.h"
+#include "Drawable.h"
+#include "Font.h"
+#include "Colormap.h"
+#include "Cursor.h"
+#include "Visual.h"
+#include "Events.h"
+#include "Init.h"
+#include "Args.h"
+#include "Client.h"
+#include "Options.h"
+#include "Splash.h"
+#include "Holder.h"
+#include "Render.h"
+#include "Trap.h"
+#include "Keyboard.h"
+#include "Pointer.h"
+#include "Reconnect.h"
+#include "Composite.h"
+#include "Shadow.h"
+#include "Utils.h"
+
+#include "Xrandr.h"
+
+#define GC XlibGC
+#define Font XlibFont
+#define KeySym XlibKeySym
+#define XID XlibXID
+#include <X11/Xlibint.h>
+#undef GC
+#undef Font
+#undef KeySym
+#undef XID
+
+#include "Xatom.h"
+#include "Xproto.h"
+
+#include "NXlib.h"
+
+#include "mibstorest.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef WATCH
+#undef DUMP
+
+/*
+ * Display a pixmap on an shadow
+ * display used for debug.
+ */
+
+#ifdef DUMP
+
+void nxagentShowPixmap(PixmapPtr pPixmap, int x, int y, int width, int height);
+
+void nxagentFbRestoreArea(PixmapPtr pPixmap, WindowPtr pWin, int xSrc, int ySrc, int width,
+ int height, int xDst, int yDst)
+#endif
+
+#ifdef WATCH
+#include "unistd.h"
+#endif
+
+extern Bool nxagentIpaq;
+extern Pixmap nxagentIconPixmap;
+extern Pixmap nxagentIconShape;
+extern Bool useXpmIcon;
+
+/*
+ * From randr/randr.c.
+ */
+
+extern Bool RRGetInfo(ScreenPtr pScreen);
+extern void RRSendConfigNotify(ScreenPtr pScreen);
+extern void RREditConnectionInfo(ScreenPtr pScreen);
+
+Window nxagentDefaultWindows[MAXSCREENS];
+Window nxagentInputWindows[MAXSCREENS];
+Window nxagentScreenSaverWindows[MAXSCREENS];
+
+#ifdef NXAGENT_ONSTART
+Atom nxagentWMStart;
+Window nxagentSplashWindow = None;
+Pixmap nxagentPixmapLogo;
+#endif
+
+ScreenPtr nxagentDefaultScreen = NULL;
+int nxagentArgc = 0;
+char **nxagentArgv = NULL;
+
+#ifdef NXAGENT_ARTSD
+
+char mcop_atom[] = "MCOPGLOBALS";
+Atom mcop_local_atom = None;
+unsigned char fromHexNibble(char c);
+void nxagentPropagateArtsdProperties(ScreenPtr pScreen, char *port);
+
+#endif
+
+Window nxagentIconWindow = None;
+Window nxagentFullscreenWindow = None;
+
+#ifdef VIEWPORT_FRAME
+
+WindowPtr nxagentViewportFrameLeft;
+WindowPtr nxagentViewportFrameRight;
+WindowPtr nxagentViewportFrameAbove;
+WindowPtr nxagentViewportFrameBelow;
+
+#endif /* #ifdef VIEWPORT_FRAME */
+
+Bool nxagentCreateScreenResources(ScreenPtr pScreen);
+void nxagentPrintAgentGeometry(char *hdrMessage, char *prefix);
+
+/*
+ * These variables are for shadowing feature.
+ */
+
+int nxagentShadowResize = 0;
+
+WindowPtr nxagentShadowWindowPtr = NULL;
+
+static XID accessPixmapID;
+static Window accessWindowID;
+static int imageByteOrder;
+static unsigned char nxagentMasterDepth;
+static unsigned char nxagentCheckDepth = 0;
+static unsigned int nxagentBppShadow;
+static unsigned int nxagentBppMaster;
+int nxagentShadowXConnectionNumber;
+GCPtr nxagentShadowGCPtr = NULL;
+PixmapPtr nxagentShadowPixmapPtr = NULL;
+char * nxagentShadowBuffer;
+unsigned char nxagentShadowDepth;
+int nxagentShadowWidth;
+int nxagentShadowHeight;
+Display * nxagentShadowDisplay;
+short nxagentShadowUid = -1;
+
+void nxagentShadowAdaptDepth(unsigned int, unsigned int, unsigned int, char **);
+
+RegionRec nxagentShadowUpdateRegion;
+
+#define NXAGENT_DEFAULT_DPI 75
+
+/*
+ * From randr/randr.c. This was originally static
+ * but we need it here.
+ */
+
+int TellChanged(WindowPtr pWin, pointer value);
+
+int nxagentBitsPerPixel(int depth)
+{
+ if (depth == 1) return 1;
+ else if (depth <= 8) return 8;
+ else if (depth <= 16) return 16;
+ else return 32;
+}
+
+void nxagentSetScreenInfo(ScreenInfo *screenInfo)
+{
+ /*
+ * Setup global screen info parameters. In the Xnest
+ * server this stuff is done after having opened the
+ * real display as Xnest lets the screen reflect the
+ * order of the remote end. Agent will instead set
+ * the order according to local endianess and swap
+ * data whenever it is appropriate.
+ *
+ * From a standard implementation:
+ *
+ * screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
+ * screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ * screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ * screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
+ *
+ * From Xnest implementation:
+ *
+ * screenInfo -> imageByteOrder = ImageByteOrder(nxagentDisplay);
+ * screenInfo -> bitmapScanlineUnit = BitmapUnit(nxagentDisplay);
+ * screenInfo -> bitmapScanlinePad = BitmapPad(nxagentDisplay);
+ * screenInfo -> bitmapBitOrder = BitmapBitOrder(nxagentDisplay);
+ */
+
+ screenInfo -> imageByteOrder = IMAGE_BYTE_ORDER;
+ screenInfo -> bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ screenInfo -> bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ screenInfo -> bitmapBitOrder = BITMAP_BIT_ORDER;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetScreenInfo: Server image order is [%d] bitmap order is [%d].\n",
+ screenInfo -> imageByteOrder, screenInfo -> bitmapBitOrder);
+
+ fprintf(stderr, "nxagentSetScreenInfo: Server scanline unit is [%d] scanline pad is [%d].\n",
+ screenInfo -> bitmapScanlineUnit, screenInfo -> bitmapScanlinePad);
+ #endif
+}
+
+void nxagentSetPixmapFormats(ScreenInfo *screenInfo)
+{
+ int i;
+
+ /*
+ * Formats are created with no care of which are supported
+ * on the real display. Creating only formats supported
+ * by the remote end makes troublesome handling migration
+ * of session from a display to another.
+ */
+
+ screenInfo -> numPixmapFormats = nxagentNumPixmapFormats;
+
+ for (i = 0; i < nxagentNumPixmapFormats; i++)
+ {
+ screenInfo -> formats[i].depth = nxagentPixmapFormats[i].depth;
+ screenInfo -> formats[i].bitsPerPixel = nxagentPixmapFormats[i].bits_per_pixel;
+ screenInfo -> formats[i].scanlinePad = nxagentPixmapFormats[i].scanline_pad;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetPixmapFormats: Set format at index [%d] to depth [%d] "
+ "bits per pixel [%d] scanline pad [%d].\n", i,
+ screenInfo -> formats[i].depth, screenInfo -> formats[i].bitsPerPixel,
+ screenInfo -> formats[i].scanlinePad);
+ #endif
+ }
+}
+
+void nxagentMinimizeFromFullScreen(ScreenPtr pScreen)
+{
+ XUnmapWindow(nxagentDisplay, nxagentFullscreenWindow);
+
+ if (nxagentIpaq)
+ {
+ XMapWindow(nxagentDisplay, nxagentIconWindow);
+ XIconifyWindow(nxagentDisplay, nxagentIconWindow,
+ DefaultScreen(nxagentDisplay));
+ }
+ else
+ {
+ XIconifyWindow(nxagentDisplay, nxagentIconWindow,
+ DefaultScreen(nxagentDisplay));
+ }
+}
+
+void nxagentMaximizeToFullScreen(ScreenPtr pScreen)
+{
+ if (nxagentIpaq)
+ {
+ XUnmapWindow(nxagentDisplay, nxagentIconWindow);
+
+ XMapWindow(nxagentDisplay, nxagentFullscreenWindow);
+ }
+ else
+ {
+/*
+ XUnmapWindow(nxagentDisplay, nxagentIconWindow);
+*/
+/*
+FIXME: We'll chech for ReparentNotify and LeaveNotify events after XReparentWindow()
+ in order to avoid the session window is iconified.
+ We could avoid the sesssion window is iconified when a LeaveNotify event is received,
+ so this check would be unnecessary.
+*/
+ struct timeval timeout;
+ int i;
+ XEvent e;
+
+ XReparentWindow(nxagentDisplay, nxagentFullscreenWindow,
+ RootWindow(nxagentDisplay, DefaultScreen(nxagentDisplay)), 0, 0);
+
+ for (i = 0; i < 100 && nxagentWMIsRunning; i++)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentMaximizeToFullscreen: WARNING! Going to wait for the ReparentNotify event.\n");
+ #endif
+
+ if (XCheckTypedWindowEvent(nxagentDisplay, nxagentFullscreenWindow, ReparentNotify, &e))
+ {
+ break;
+ }
+
+ XSync(nxagentDisplay, 0);
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 50 * 1000;
+
+ nxagentWaitEvents(nxagentDisplay, &timeout);
+ }
+
+ XMapRaised(nxagentDisplay, nxagentFullscreenWindow);
+
+ XIconifyWindow(nxagentDisplay, nxagentIconWindow,
+ DefaultScreen(nxagentDisplay));
+
+ while (XCheckTypedWindowEvent(nxagentDisplay, nxagentFullscreenWindow, LeaveNotify, &e));
+/*
+ XMapWindow(nxagentDisplay, nxagentIconWindow);
+*/
+ }
+}
+
+Window nxagentCreateIconWindow()
+{
+ XSetWindowAttributes attributes;
+ unsigned long valuemask;
+ char* window_name;
+ XTextProperty windowName;
+ XSizeHints sizeHints;
+ XWMHints wmHints;
+ Window w;
+ Mask mask;
+
+ /*
+ * Create icon window.
+ */
+
+ attributes.override_redirect = False;
+ attributes.colormap = DefaultColormap(nxagentDisplay, DefaultScreen(nxagentDisplay));
+ attributes.background_pixmap = nxagentScreenSaverPixmap;
+ valuemask = CWOverrideRedirect | CWBackPixmap | CWColormap;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateIconWindow: Going to create new icon window.\n");
+ #endif
+
+ w = XCreateWindow(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ 0, 0, 1, 1, 0,
+ DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay)),
+ InputOutput,
+ DefaultVisual(nxagentDisplay, DefaultScreen(nxagentDisplay)),
+ valuemask, &attributes);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateIconWindow: Created new icon window with id [%ld].\n",
+ nxagentIconWindow);
+ #endif
+
+ /*
+ * Set hints to the window manager for the icon window.
+ */
+
+ window_name = nxagentWindowName;
+ XStringListToTextProperty(&window_name, 1, &windowName);
+ sizeHints.flags = PMinSize | PMaxSize;
+ sizeHints.min_width = sizeHints.max_width = 1;
+ sizeHints.min_height = sizeHints.max_height = 1;
+ wmHints.flags = IconPixmapHint | IconMaskHint;
+ wmHints.initial_state = IconicState;
+ wmHints.icon_pixmap = nxagentIconPixmap;
+
+ if (useXpmIcon)
+ {
+ wmHints.icon_mask = nxagentIconShape;
+ wmHints.flags = IconPixmapHint | IconMaskHint;
+ }
+ else
+ {
+ wmHints.flags = StateHint | IconPixmapHint;
+ }
+
+ XSetWMProperties(nxagentDisplay, w,
+ &windowName, &windowName,
+ NULL , 0 , &sizeHints, &wmHints, NULL);
+
+ /*
+ * Enable events from the icon window.
+ */
+
+ nxagentGetDefaultEventMask(&mask);
+
+ XSelectInput(nxagentDisplay, w, (mask & ~(KeyPressMask |
+ KeyReleaseMask)) | StructureNotifyMask);
+
+ /*
+ * Notify to client if user closes icon window.
+ */
+
+ if (nxagentWMIsRunning && !nxagentOption(Rootless))
+ {
+ XlibAtom deleteWMAtom = nxagentAtoms[2]; /* WM_DELETE_WINDOW */
+
+ XSetWMProtocols(nxagentDisplay, w, &deleteWMAtom, 1);
+ }
+
+ return w;
+}
+
+Bool nxagentMagicPixelZone(int x, int y)
+{
+ return (x >= nxagentOption(Width) - 1 && y < 1);
+}
+
+void nxagentSetScreenSaverTime(void)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetScreenSaverTime: ScreenSaverTime was [%lu], ScreenSaverInterval was [%lu].\n",
+ ScreenSaverTime, ScreenSaverInterval);
+ #endif
+
+ /*
+ * More than one timeout could be used here,
+ * to make use of screen-saver handler not
+ * only for the timeout feature. In a case
+ * like this, the lower timeout have to be
+ * used as ScreenSaverTime.
+ */
+
+ if (nxagentAutoDisconnectTimeout > 0)
+ {
+ ScreenSaverTime = nxagentAutoDisconnectTimeout;
+ }
+
+ ScreenSaverInterval = ScreenSaverTime;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetScreenSaverTime: ScreenSaverTime now is [%lu], ScreenSaverInterval now is [%lu].\n",
+ ScreenSaverTime, ScreenSaverInterval);
+ #endif
+}
+
+static Bool nxagentSaveScreen(ScreenPtr pScreen, int what)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentSaveScreen: Called for screen at [%p] with parameter [%d].\n",
+ (void *) pScreen, what);
+
+ fprintf(stderr, "nxagentSaveScreen: SCREEN_SAVER_ON is [%d] SCREEN_SAVER_OFF is [%d] "
+ "SCREEN_SAVER_FORCER is [%d] SCREEN_SAVER_CYCLE is [%d].\n",
+ SCREEN_SAVER_ON, SCREEN_SAVER_OFF, SCREEN_SAVER_FORCER,
+ SCREEN_SAVER_CYCLE);
+ #endif
+
+ /*
+ * We need only to reset the timeouts
+ * in this case.
+ */
+
+ if (what == SCREEN_SAVER_OFF)
+ {
+ nxagentAutoDisconnectTimeout = nxagentOption(Timeout) * MILLI_PER_SECOND;
+
+ return 1;
+ }
+
+ /*
+ * The lastDeviceEventTime is updated every time
+ * a device event is received, and it is used by
+ * WaitForSomething() to know when the SaveScreens()
+ * function should be called. This solution doesn't
+ * take care of a pointer button not released, so
+ * we have to handle this case by ourselves.
+ */
+
+/*
+FIXME: Do we need to check the key grab if the
+ autorepeat feature is disabled?
+*/
+ if (inputInfo.pointer -> button -> buttonsDown > 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSaveScreen: Ignoring timeout, there is a pointer button down.\n");
+ #endif
+
+ /*
+ * Returning 0 the SaveScreens() function
+ * (which calls this one) tries to build
+ * a screen-saver creating a new window.
+ * We don't want this, so we return 1 in
+ * any case.
+ */
+
+ return 1;
+ }
+
+ /*
+ * Handling the auto-disconnect feature.
+ * If there is any client attached and the persisten-
+ * ce is allowed then leave the session running, else
+ * terminate it. It should use something less brutal,
+ * though raising a signal should ensure that the code
+ * follows the usual execution path.
+ */
+
+ if (nxagentOption(Timeout) > 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSaveScreen: Auto-disconnect timeout was [%d].\n",
+ nxagentAutoDisconnectTimeout);
+ #endif
+
+ nxagentAutoDisconnectTimeout -= ScreenSaverTime;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSaveScreen: Auto-disconnect timeout is [%d].\n",
+ nxagentAutoDisconnectTimeout);
+ #endif
+
+ if (nxagentSessionState == SESSION_UP &&
+ nxagentAutoDisconnectTimeout <= 0)
+ {
+ nxagentAutoDisconnectTimeout = nxagentOption(Timeout) * MILLI_PER_SECOND;
+
+ if (nxagentClients == 0)
+ {
+ fprintf(stderr, "Info: Terminating session with no client running.\n");
+
+ raise(SIGTERM);
+ }
+ else if (nxagentOption(Persistent) == 0)
+ {
+ fprintf(stderr, "Info: Terminating session with persistence not allowed.\n");
+
+ raise(SIGTERM);
+ }
+ else
+ {
+ fprintf(stderr, "Info: Suspending session with %d clients running.\n",
+ nxagentClients);
+
+ raise(SIGHUP);
+ }
+ }
+ }
+
+ return 1;
+}
+
+Bool nxagentCreateScreenResources(ScreenPtr pScreen)
+{
+ Bool ret;
+
+ CreatePixmapProcPtr savedCreatePixmap = pScreen->CreatePixmap;
+ ModifyPixmapHeaderProcPtr savedModifyPixmapHeader = pScreen->ModifyPixmapHeader;
+
+ pScreen->CreatePixmap = fbCreatePixmap;
+ pScreen->ModifyPixmapHeader = miModifyPixmapHeader;
+ ret = miCreateScreenResources(pScreen);
+
+ pScreen->CreatePixmap = savedCreatePixmap;
+ pScreen->ModifyPixmapHeader = savedModifyPixmapHeader;
+
+ return ret;
+}
+
+static Bool nxagentCursorOffScreen(ScreenPtr *pPtrScreen, int *x, int *y)
+{
+ return False;
+}
+
+static void nxagentCrossScreen(ScreenPtr pScreen, Bool entering)
+{
+}
+
+static miPointerScreenFuncRec nxagentPointerCursorFuncs =
+{
+ nxagentCursorOffScreen,
+ nxagentCrossScreen,
+ miPointerWarpCursor
+};
+
+#ifdef VIEWPORT_FRAME
+
+void nxagentInitViewportFrame(ScreenPtr pScreen, WindowPtr pRootWin)
+{
+ int error = Success;
+ VisualID visual = 0;
+ int i;
+ XID xid;
+
+ if (nxagentOption(Rootless))
+ {
+ return;
+ }
+
+ for (i = 0; i < pScreen -> numDepths; i++)
+ {
+ if (pScreen -> allowedDepths[i].depth == pRootWin -> drawable.depth)
+ {
+ visual = pScreen -> allowedDepths[i].vids[0];
+ break;
+ }
+ }
+
+ /*
+ * It is not necessary create the windows on the real X server. But this
+ * windows are not visible. Create them it is not a great effort, and avoids
+ * many errors.
+ *
+ * nxagentScreenTrap = True;
+ */
+
+ xid = FakeClientID(serverClient -> index);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid);
+ #endif
+
+ nxagentViewportFrameLeft = CreateWindow(xid, pRootWin, -NXAGENT_FRAME_WIDTH, 0, NXAGENT_FRAME_WIDTH,
+ pRootWin -> drawable.height,
+ 0, InputOutput, 0, NULL,
+ pRootWin -> drawable.depth,
+ serverClient, visual, &error);
+
+ AddResource(xid, RT_WINDOW, (pointer) nxagentViewportFrameLeft);
+
+ if (error != Success)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameLeft.\n");
+ #endif
+
+ error = Success;
+ }
+
+ xid = FakeClientID(serverClient -> index);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid);
+ #endif
+
+ nxagentViewportFrameRight = CreateWindow(xid, pRootWin, pRootWin -> drawable.width, 0,
+ NXAGENT_FRAME_WIDTH,
+ pRootWin -> drawable.height,
+ 0, InputOutput, 0, NULL,
+ pRootWin -> drawable.depth,
+ serverClient, visual,
+ &error);
+
+ AddResource(xid, RT_WINDOW, (pointer) nxagentViewportFrameRight);
+
+ if (error != Success)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameRight.\n");
+ #endif
+
+ error = Success;
+ }
+
+ xid = FakeClientID(serverClient -> index);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid);
+ #endif
+
+ nxagentViewportFrameAbove = CreateWindow(xid, pRootWin, 0, -NXAGENT_FRAME_WIDTH,
+ pRootWin -> drawable.width,
+ NXAGENT_FRAME_WIDTH, 0,
+ InputOutput, 0, NULL,
+ pRootWin -> drawable.depth,
+ serverClient, visual,
+ &error);
+
+ AddResource(xid, RT_WINDOW, (pointer) nxagentViewportFrameAbove);
+
+ if (error != Success)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameAbove.\n");
+ #endif
+
+ error = Success;
+ }
+
+ xid = FakeClientID(serverClient -> index);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid);
+ #endif
+
+ nxagentViewportFrameBelow = CreateWindow(xid, pRootWin, 0,
+ pRootWin -> drawable.height,
+ pRootWin -> drawable.width,
+ NXAGENT_FRAME_WIDTH, 0,
+ InputOutput, 0, NULL,
+ pRootWin -> drawable.depth,
+ serverClient, visual, &error);
+
+ AddResource(xid, RT_WINDOW, (pointer) nxagentViewportFrameBelow);
+
+ if (error != Success)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameBelow.\n");
+ #endif
+ }
+
+ nxagentViewportFrameLeft -> overrideRedirect = 1;
+ nxagentViewportFrameRight -> overrideRedirect = 1;
+ nxagentViewportFrameAbove -> overrideRedirect = 1;
+ nxagentViewportFrameBelow -> overrideRedirect = 1;
+
+ MapWindow(nxagentViewportFrameLeft, serverClient);
+ MapWindow(nxagentViewportFrameRight, serverClient);
+ MapWindow(nxagentViewportFrameAbove, serverClient);
+ MapWindow(nxagentViewportFrameBelow, serverClient);
+
+ /*
+ * nxagentScreenTrap = False;
+ */
+}
+
+#endif /* #ifdef VIEWPORT_FRAME */
+
+void nxagentPrintAgentGeometry(char *hdrMessage, char *prefix)
+{
+ #ifdef WARNING
+
+ if (prefix == NULL)
+ {
+ prefix = "";
+ }
+
+ if (hdrMessage)
+ {
+ fprintf(stderr, "--------------- %s -----------------.\n", hdrMessage);
+ }
+
+ fprintf(stderr, "%s Root window at offset (%d,%d) size (%d,%d).\n", prefix,
+ nxagentOption(RootX), nxagentOption(RootY),
+ nxagentOption(RootWidth), nxagentOption(RootHeight));
+
+ fprintf(stderr, "%s Default window at offset (%d,%d) size (%d,%d) border size %d.\n", prefix,
+ nxagentOption(X), nxagentOption(Y), nxagentOption(Width), nxagentOption(Height),
+ nxagentOption(BorderWidth));
+
+ fprintf(stderr, "%s Span between root window and default window is (%d,%d).\n", prefix,
+ nxagentOption(ViewportXSpan), nxagentOption(ViewportYSpan));
+
+ fprintf(stderr, "%s Default window in window mode has offset (%d,%d) and size (%d,%d).\n", prefix,
+ nxagentOption(SavedX), nxagentOption(SavedY), nxagentOption(SavedWidth), nxagentOption(SavedHeight));
+
+ fprintf(stderr, "%s Fullscreen is %s.\n", prefix,
+ nxagentOption(Fullscreen) ? "ON" : "OFF");
+
+ fprintf(stderr, "%s Desktop resize mode is %s.\n", prefix,
+ nxagentOption(DesktopResize) ? "ON" : "OFF");
+
+ fprintf(stderr, "%s Resize desktop at startup is %s.\n", prefix,
+ nxagentResizeDesktopAtStartup ? "ON" : "OFF");
+
+ #endif
+}
+
+static int nxagentColorOffset(unsigned long mask)
+{
+ int count;
+
+ for (count = 0; !(mask & 1) && count < 32; count++)
+ {
+ mask >>= 1;
+ }
+
+ return count;
+}
+
+Bool nxagentOpenScreen(int index, ScreenPtr pScreen,
+ int argc, char *argv[])
+{
+ VisualPtr visuals;
+ DepthPtr depths;
+ int numVisuals, numDepths;
+ int i, j, depthIndex;
+ unsigned long valuemask;
+ XSetWindowAttributes attributes;
+ XWindowAttributes gattributes;
+ XSizeHints sizeHints;
+ XWMHints wmHints;
+ Mask mask;
+ Bool resetAgentPosition = False;
+
+ VisualID defaultVisual;
+ int rootDepth;
+
+ pointer pFrameBufferBits;
+ int bitsPerPixel;
+ int sizeInBytes;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Called for screen index [%d].\n",
+ index);
+ #endif
+
+ if (nxagentRenderEnable && nxagentReconnectTrap == False)
+ {
+ PictureScreenPrivateIndex = -1;
+ }
+
+ nxagentDefaultScreen = pScreen;
+
+ nxagentQueryAtoms(pScreen);
+
+ #ifdef NXAGENT_ONSTART
+ nxagentWMStart = nxagentAtoms[3]; /* WM_NX_READY */
+ #endif
+
+ /*
+ * Forced geometry parameter
+ * to user geometry.
+ */
+
+ if (nxagentResizeDesktopAtStartup)
+ {
+ if (nxagentUserGeometry.flag & XValue)
+ {
+ nxagentChangeOption(X, nxagentUserGeometry.X);
+ }
+
+ if (nxagentUserGeometry.flag & YValue)
+ {
+ nxagentChangeOption(Y, nxagentUserGeometry.Y);
+ }
+
+ if (nxagentUserGeometry.flag & WidthValue)
+ {
+ nxagentChangeOption(Width, nxagentUserGeometry.Width);
+ nxagentChangeOption(RootWidth, nxagentUserGeometry.Width);
+
+ if (nxagentOption(SavedWidth) > nxagentUserGeometry.Width)
+ {
+ nxagentChangeOption(SavedWidth, nxagentUserGeometry.Width);
+ }
+ }
+
+ if (nxagentUserGeometry.flag & HeightValue)
+ {
+ nxagentChangeOption(Height, nxagentUserGeometry.Height);
+ nxagentChangeOption(RootHeight, nxagentUserGeometry.Height);
+
+ if (nxagentOption(SavedHeight) > nxagentUserGeometry.Height)
+ {
+ nxagentChangeOption(SavedHeight, nxagentUserGeometry.Height);
+ }
+ }
+ }
+
+ /*
+ * This is first time the
+ * screen is initialized.
+ * Filling the geometry parameter
+ * from user geometry.
+ */
+
+ if (nxagentReconnectTrap == False)
+ {
+ if (nxagentUserGeometry.flag & XValue)
+ {
+ nxagentChangeOption(X, nxagentUserGeometry.X);
+ }
+
+ if (nxagentUserGeometry.flag & YValue)
+ {
+ nxagentChangeOption(Y, nxagentUserGeometry.Y);
+ }
+
+ if (nxagentUserGeometry.flag & WidthValue)
+ {
+ nxagentChangeOption(RootWidth, nxagentUserGeometry.Width);
+ }
+
+ if (nxagentUserGeometry.flag & HeightValue)
+ {
+ nxagentChangeOption(RootHeight, nxagentUserGeometry.Height);
+ }
+ }
+ else if (nxagentWMIsRunning && !nxagentOption(Rootless) && !nxagentOption(Fullscreen))
+ {
+ /*
+ * At reconnection, try to estimate the shift due to WM reparenting.
+ */
+
+ if (nxagentOption(X) >= 6)
+ {
+ nxagentChangeOption(X, nxagentOption(X) - 6);
+ }
+
+ if (nxagentOption(Y) >= 25)
+ {
+ nxagentChangeOption(Y, nxagentOption(Y) - 25);
+ }
+ }
+
+ /*
+ * Determine the size of the root window.
+ * It is the maximum size of the screen
+ * if we are either in rootless or in
+ * fullscreen mode.
+ */
+
+ if (nxagentOption(Rootless) == False && nxagentWMIsRunning == False)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Forcing fullscreen mode with no window manager running.\n");
+ #endif
+
+ nxagentChangeOption(Fullscreen, True);
+
+ if (nxagentOption(ClientOs) == ClientOsWinnt &&
+ (nxagentReconnectTrap == False || nxagentResizeDesktopAtStartup))
+ {
+ NXSetExposeParameters(nxagentDisplay, 0, 0, 0);
+ }
+ }
+
+ if (nxagentOption(Fullscreen) &&
+ nxagentWMIsRunning &&
+ nxagentReconnectTrap &&
+ nxagentResizeDesktopAtStartup == False &&
+ nxagentXServerGeometryChanged())
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Forcing window mode with server geometry changed.\n");
+ #endif
+
+ nxagentChangeOption(Fullscreen, False);
+
+ nxagentChangeOption(AllScreens, False);
+
+ nxagentFullscreenWindow = 0;
+
+ resetAgentPosition = True;
+ }
+
+ if (nxagentOption(Fullscreen))
+ {
+ nxagentChangeOption(X, 0);
+ nxagentChangeOption(Y, 0);
+
+ nxagentChangeOption(Width, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+ nxagentChangeOption(Height, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+
+ nxagentChangeOption(BorderWidth, 0);
+
+ if (nxagentReconnectTrap == False || nxagentResizeDesktopAtStartup)
+ {
+ nxagentChangeOption(RootWidth, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+ nxagentChangeOption(RootHeight, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+
+ if (nxagentOption(RootWidth) > WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)))
+ {
+ nxagentChangeOption(SavedWidth, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4);
+ }
+ else
+ {
+ nxagentChangeOption(SavedWidth, nxagentOption(RootWidth));
+ }
+
+ if (nxagentOption(RootHeight) > HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)))
+ {
+ nxagentChangeOption(SavedHeight, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4);
+ }
+ else
+ {
+ nxagentChangeOption(SavedHeight, nxagentOption(RootHeight));
+ }
+ }
+
+ nxagentChangeOption(RootX, ((WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) -
+ nxagentOption(RootWidth)) / 2));
+ nxagentChangeOption(RootY, ((HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) -
+ nxagentOption(RootHeight)) / 2));
+ }
+ else
+ {
+ nxagentChangeOption(BorderWidth, 0);
+
+ if (nxagentReconnectTrap == False)
+ {
+ nxagentChangeOption(RootX, 0);
+ nxagentChangeOption(RootY, 0);
+
+ nxagentChangeOption(Width, nxagentOption(RootWidth));
+ nxagentChangeOption(Height, nxagentOption(RootHeight));
+ }
+
+ /*
+ * Be sure that the agent window won't be bigger
+ * than the root window.
+ */
+
+ if (nxagentOption(Width) > nxagentOption(RootWidth))
+ {
+ nxagentChangeOption(Width, nxagentOption(RootWidth));
+ }
+
+ if (nxagentOption(Height) > nxagentOption(RootHeight))
+ {
+ nxagentChangeOption(Height, nxagentOption(RootHeight));
+ }
+
+ /*
+ * Be sure that the agent window won't be bigger
+ * than the X server root window.
+ */
+
+ if (nxagentOption(Width) > WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)))
+ {
+ nxagentChangeOption(Width, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4);
+ }
+
+ if (nxagentOption(Height) > HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)))
+ {
+ nxagentChangeOption(Height, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4);
+ }
+
+ /*
+ * Forcing the agent window geometry to be equal to
+ * the root window geometry the first time the
+ * screen is initialized if the geometry hasn't been
+ * esplicitly set in the option file and if
+ * the root window isn't bigger than the X server
+ * root window..
+ */
+
+ if (nxagentReconnectTrap == False)
+ {
+ if ((nxagentOption(RootWidth) < WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay))) &&
+ !(nxagentUserGeometry.flag & WidthValue))
+ {
+ nxagentChangeOption(Width, nxagentOption(RootWidth));
+ }
+
+ if ((nxagentOption(RootHeight) < HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))) &&
+ !(nxagentUserGeometry.flag & HeightValue))
+ {
+ nxagentChangeOption(Height, nxagentOption(RootHeight));
+ }
+ }
+
+ if (resetAgentPosition)
+ {
+ nxagentChangeOption(X, ((WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) -
+ nxagentOption(Width)) / 2));
+
+ nxagentChangeOption(Y, ((HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) -
+ nxagentOption(Height)) / 2));
+ }
+
+ nxagentChangeOption(SavedWidth, nxagentOption(RootWidth));
+ nxagentChangeOption(SavedHeight, nxagentOption(RootHeight));
+ }
+
+ if (nxagentOption(Rootless))
+ {
+ nxagentChangeOption(RootWidth, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+ nxagentChangeOption(RootHeight, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+ }
+
+ nxagentChangeOption(SavedRootWidth, nxagentOption(RootWidth));
+ nxagentChangeOption(SavedRootHeight, nxagentOption(RootHeight));
+
+ nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth));
+ nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight));
+
+ if (nxagentReconnectTrap == 0)
+ {
+ if (nxagentOption(Persistent))
+ {
+ nxagentArgc = argc;
+ nxagentArgv = argv;
+ }
+
+ #ifdef NXAGENT_TIMESTAMP
+
+ {
+ extern unsigned long startTime;
+
+ fprintf(stderr, "Screen: going to open screen, time is [%d] milliseconds.\n",
+ GetTimeInMillis() - startTime);
+ }
+
+ #endif
+
+ /*
+ * Initialize all our privates.
+ */
+
+ if (AllocateWindowPrivate(pScreen, nxagentWindowPrivateIndex, sizeof(nxagentPrivWindowRec)) == 0 ||
+ AllocateGCPrivate(pScreen, nxagentGCPrivateIndex, sizeof(nxagentPrivGC)) == 0 ||
+ AllocateClientPrivate(nxagentClientPrivateIndex, sizeof(PrivClientRec)) == 0 ||
+ AllocatePixmapPrivate(pScreen, nxagentPixmapPrivateIndex, sizeof(nxagentPrivPixmapRec)) == 0)
+ {
+ return False;
+ }
+
+ /*
+ * Initialize the depths.
+ */
+
+ depths = (DepthPtr) xalloc(nxagentNumDepths * sizeof(DepthRec));
+
+ for (i = 0; i < nxagentNumDepths; i++)
+ {
+ depths[i].depth = nxagentDepths[i];
+ depths[i].numVids = 0;
+ depths[i].vids = (VisualID *) xalloc(MAXVISUALSPERDEPTH * sizeof(VisualID));
+ }
+
+ /*
+ * Initialize the visuals.
+ */
+
+ numVisuals = 0;
+ numDepths = nxagentNumDepths;
+
+ visuals = (VisualPtr) xalloc(nxagentNumVisuals * sizeof(VisualRec));
+
+ for (i = 0; i < nxagentNumVisuals; i++)
+ {
+ visuals[numVisuals].vid = FakeClientID(0);
+ visuals[numVisuals].class = nxagentVisuals[i].class;
+ visuals[numVisuals].bitsPerRGBValue = nxagentVisuals[i].bits_per_rgb;
+ visuals[numVisuals].ColormapEntries = nxagentVisuals[i].colormap_size;
+ visuals[numVisuals].nplanes = nxagentVisuals[i].depth;
+ visuals[numVisuals].redMask = nxagentVisuals[i].red_mask;
+ visuals[numVisuals].greenMask = nxagentVisuals[i].green_mask;
+ visuals[numVisuals].blueMask = nxagentVisuals[i].blue_mask;
+ visuals[numVisuals].offsetRed = nxagentColorOffset(nxagentVisuals[i].red_mask);
+ visuals[numVisuals].offsetGreen = nxagentColorOffset(nxagentVisuals[i].green_mask);
+ visuals[numVisuals].offsetBlue = nxagentColorOffset(nxagentVisuals[i].blue_mask);
+
+ /*
+ * Check for and remove the duplicates.
+ */
+
+ for (j = 0; j < numVisuals; j++)
+ {
+ if (visuals[numVisuals].class == visuals[j].class &&
+ visuals[numVisuals].bitsPerRGBValue == visuals[j].bitsPerRGBValue &&
+ visuals[numVisuals].ColormapEntries == visuals[j].ColormapEntries &&
+ visuals[numVisuals].nplanes == visuals[j].nplanes &&
+ visuals[numVisuals].redMask == visuals[j].redMask &&
+ visuals[numVisuals].greenMask == visuals[j].greenMask &&
+ visuals[numVisuals].blueMask == visuals[j].blueMask &&
+ visuals[numVisuals].offsetRed == visuals[j].offsetRed &&
+ visuals[numVisuals].offsetGreen == visuals[j].offsetGreen &&
+ visuals[numVisuals].offsetBlue == visuals[j].offsetBlue)
+ break;
+ }
+
+ if (j < numVisuals)
+ continue;
+
+ depthIndex = UNDEFINED;
+
+ for (j = 0; j < numDepths; j++)
+ {
+ if (depths[j].depth == nxagentVisuals[i].depth)
+ {
+ depthIndex = j;
+ break;
+ }
+ }
+
+ if (depthIndex == UNDEFINED)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentOpenScreen: WARNING! Can't find a matching depth for visual depth [%d].\n",
+ nxagentVisuals[i].depth);
+ #endif
+
+ depthIndex = numDepths;
+
+ depths[depthIndex].depth = nxagentVisuals[i].depth;
+ depths[depthIndex].numVids = 0;
+ depths[depthIndex].vids = (VisualID *) xalloc(MAXVISUALSPERDEPTH * sizeof(VisualID));
+
+ numDepths++;
+ }
+
+ if (depths[depthIndex].numVids >= MAXVISUALSPERDEPTH)
+ {
+ FatalError("Visual table overflow");
+ }
+
+ depths[depthIndex].vids[depths[depthIndex].numVids] = visuals[numVisuals].vid;
+
+ depths[depthIndex].numVids++;
+
+ numVisuals++;
+ }
+
+ defaultVisual = visuals[nxagentDefaultVisualIndex].vid;
+ rootDepth = visuals[nxagentDefaultVisualIndex].nplanes;
+
+ nxagentInitAlphaVisual();
+
+ bitsPerPixel = nxagentBitsPerPixel(rootDepth);
+
+ if (bitsPerPixel == 1)
+ {
+ sizeInBytes = PixmapBytePad(nxagentOption(RootWidth), rootDepth) * nxagentOption(RootHeight);
+ }
+ else
+ {
+ sizeInBytes = PixmapBytePad(nxagentOption(RootWidth), rootDepth) * nxagentOption(RootHeight) * bitsPerPixel/8;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Frame buffer allocated. rootDepth "
+ "[%d] bitsPerPixel [%d] sizeInBytes [%d]\n", rootDepth, bitsPerPixel, sizeInBytes);
+ #endif
+
+ pFrameBufferBits = (char *) Xalloc(sizeInBytes);
+
+ if (!pFrameBufferBits)
+ {
+ return FALSE;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Before fbScreenInit numVisuals [%d] numDepths [%d] "
+ "rootDepth [%d] defaultVisual [%ld].\n", numVisuals, numDepths,
+ rootDepth, defaultVisual);
+ #endif
+
+ if (monitorResolution < 1)
+ {
+ monitorResolution = NXAGENT_DEFAULT_DPI;
+ }
+
+ if (!fbScreenInit(pScreen, pFrameBufferBits, nxagentOption(RootWidth), nxagentOption(RootHeight),
+ monitorResolution, monitorResolution, PixmapBytePad(nxagentOption(RootWidth), rootDepth), bitsPerPixel))
+ {
+ return FALSE;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: After fbScreenInit numVisuals [%d] numDepths [%d] "
+ "rootDepth [%d] defaultVisual [%ld].\n", numVisuals, numDepths,
+ rootDepth, defaultVisual);
+ #endif
+
+ /*
+ * Complete the initialization of the GLX
+ * extension. This will add the GLX visuals
+ * and will modify numVisuals and numDepths.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Before GLX numVisuals [%d] numDepths [%d] "
+ "rootDepth [%d] defaultVisual [%ld].\n", numVisuals, numDepths,
+ rootDepth, defaultVisual);
+ #endif
+
+ nxagentInitGlxExtension(&visuals, &depths, &numVisuals, &numDepths,
+ &rootDepth, &defaultVisual);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: After GLX numVisuals [%d] numDepths [%d] "
+ "rootDepth [%d] defaultVisual [%ld].\n", numVisuals, numDepths,
+ rootDepth, defaultVisual);
+ #endif
+
+ /*
+ * Replace the visuals and depths initialized
+ * by fbScreenInit with our own.
+ */
+
+ xfree(pScreen -> visuals);
+ xfree(pScreen -> allowedDepths);
+
+ pScreen -> visuals = visuals;
+ pScreen -> allowedDepths = depths;
+ pScreen -> numVisuals = numVisuals;
+ pScreen -> numDepths = numDepths;
+ pScreen -> rootVisual = defaultVisual;
+ pScreen -> rootDepth = rootDepth;
+
+ /*
+ * Complete the initialization of the RANDR
+ * extension.
+ */
+
+ nxagentInitRandRExtension(pScreen);
+
+ /*
+ * Set up the internal structures used for
+ * tracking the proxy resources associated
+ * to the unpack and split operations.
+ */
+
+ nxagentInitSplitResources();
+ nxagentInitUnpackResources();
+
+ /*
+ * Initializing the pixmaps that will serve as
+ * "placeholders" in lazy encoding. We need one
+ * pixmap for each depth.
+ */
+
+ for (i = 0; i < numDepths; i++)
+ {
+ nxagentMarkPlaceholderNotLoaded(i);
+ }
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentOpenScreen: Watchpoint 7.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+N/A
+*/
+
+ sleep(30);
+
+ #endif
+
+ if (nxagentParentWindow != 0)
+ {
+ /*
+ * This would cause a GetWindowAttributes
+ * and a GetGeometry (asynchronous) reply.
+ */
+
+ XGetWindowAttributes(nxagentDisplay, nxagentParentWindow, &gattributes);
+
+ nxagentChangeOption(Width, gattributes.width);
+ nxagentChangeOption(Height, gattributes.height);
+ }
+
+ if (nxagentOption(AllScreens))
+ {
+ attributes.override_redirect = True;
+ }
+
+ if (nxagentOption(Fullscreen))
+ {
+ /*
+ * We need to disable the host's screensaver or
+ * it will otherwise grab the screen even if it
+ * is under agent's control.
+ */
+
+ XSetScreenSaver(nxagentDisplay, 0, 0, DefaultExposures, DefaultBlanking);
+ }
+
+ if (nxagentTrue24)
+ {
+ fbGetScreenPrivate(pScreen) -> win32bpp = visuals[nxagentDefaultVisualIndex].nplanes;
+ fbGetScreenPrivate(pScreen) -> pix32bpp = visuals[nxagentDefaultVisualIndex].nplanes;
+ }
+ else
+ {
+ fbGetScreenPrivate(pScreen) -> win32bpp = 32;
+ fbGetScreenPrivate(pScreen) -> pix32bpp = 32;
+ }
+
+ /*
+ * We call miScreenInit with NULL in place of the screen area if we
+ * don't want to initialize the frame buffer.
+ *
+ * if (!miScreenInit(pScreen, NULL, nxagentOption(RootWidth),
+ * nxagentOption(RootHeight), 1, 1, nxagentOption(RootWidth),
+ * visuals[nxagentDefaultVisualIndex].nplanes, / * Root depth. * /
+ * numDepths, depths,
+ * visuals[nxagentDefaultVisualIndex].vid,* Root visual. * /
+ * numVisuals, visuals))
+ * return FALSE;
+ */
+
+ pScreen->defColormap = (Colormap) FakeClientID(0);
+ pScreen->minInstalledCmaps = MINCMAPS;
+ pScreen->maxInstalledCmaps = MAXCMAPS;
+
+ pScreen->whitePixel = nxagentWhitePixel;
+ pScreen->blackPixel = nxagentBlackPixel;
+ /* rgf */
+ /* GCperDepth */
+ /* PixmapPerDepth */
+ /* WindowPrivateLen */
+ /* WindowPrivateSizes */
+ /* totalWindowSize */
+ /* GCPrivateLen */
+ /* GCPrivateSizes */
+ /* totalGCSize */
+
+ /*
+ * Random screen procedures.
+ */
+
+ pScreen->CloseScreen = nxagentCloseScreen;
+ pScreen->QueryBestSize = nxagentQueryBestSize;
+ pScreen->SaveScreen = nxagentSaveScreen;
+ pScreen->GetImage = nxagentGetImage;
+ pScreen->GetSpans = nxagentGetSpans;
+ pScreen->PointerNonInterestBox = (void (*)()) 0;
+ pScreen->SourceValidate = (void (*)()) 0;
+
+ pScreen->CreateScreenResources = nxagentCreateScreenResources;
+
+ /*
+ * Window Procedures.
+ *
+ * Note that the following functions are not
+ * replaced with nxagent counterparts:
+ *
+ * ValidateTreeProcPtr ValidateTree;
+ * ClearToBackgroundProcPtr ClearToBackground;
+ *
+ * Note also that the ConfigureWindow procedure
+ * has not a pointer in the screen structure.
+ */
+
+ pScreen->CreateWindow = nxagentCreateWindow;
+ pScreen->DestroyWindow = nxagentDestroyWindow;
+ pScreen->PositionWindow = nxagentPositionWindow;
+ pScreen->ChangeWindowAttributes = nxagentChangeWindowAttributes;
+ pScreen->RealizeWindow = nxagentRealizeWindow;
+ pScreen->UnrealizeWindow = nxagentUnrealizeWindow;
+ pScreen->PostValidateTree = nxagentPostValidateTree;
+ pScreen->WindowExposures = nxagentWindowExposures;
+ pScreen->PaintWindowBackground = nxagentPaintWindowBackground;
+ pScreen->PaintWindowBorder = nxagentPaintWindowBorder;
+ pScreen->CopyWindow = nxagentCopyWindow;
+ pScreen->ClipNotify = nxagentClipNotify;
+ pScreen->RestackWindow = nxagentRestackWindow;
+ pScreen->ReparentWindow = nxagentReparentWindow;
+
+ /*
+ * Pixmap procedures.
+ */
+
+ pScreen->CreatePixmap = nxagentCreatePixmap;
+ pScreen->DestroyPixmap = nxagentDestroyPixmap;
+
+ /*
+ * This is originally miModifyPixmapHeader()
+ * from miscrinit.c. It is used to recycle
+ * the scratch pixmap for this screen.
+ */
+
+ pScreen->ModifyPixmapHeader = nxagentModifyPixmapHeader;
+
+ /*
+ * Font procedures.
+ */
+
+ pScreen->RealizeFont = nxagentRealizeFont;
+ pScreen->UnrealizeFont = nxagentUnrealizeFont;
+
+ /*
+ * GC procedures.
+ */
+
+ pScreen->CreateGC = nxagentCreateGC;
+ pScreen->BitmapToRegion = nxagentPixmapToRegion;
+
+ /*
+ * Colormap procedures.
+ */
+
+ pScreen->CreateColormap = nxagentCreateColormap;
+ pScreen->DestroyColormap = nxagentDestroyColormap;
+ pScreen->InstallColormap = nxagentInstallColormap;
+ pScreen->UninstallColormap = nxagentUninstallColormap;
+ pScreen->ListInstalledColormaps = nxagentListInstalledColormaps;
+ pScreen->StoreColors = nxagentStoreColors;
+ pScreen->ResolveColor = nxagentResolveColor;
+
+ /*
+ * Backing store procedures.
+ */
+
+ pScreen->SaveDoomedAreas = (void (*)()) 0;
+ pScreen->RestoreAreas = (RegionPtr (*)()) 0;
+ pScreen->ExposeCopy = (void (*)()) 0;
+ pScreen->TranslateBackingStore = (RegionPtr (*)()) 0;
+ pScreen->ClearBackingStore = (RegionPtr (*)()) 0;
+ pScreen->DrawGuarantee = (void (*)()) 0;
+
+ if (enableBackingStore == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Going to initialize backing store.\n");
+ #endif
+
+ pScreen -> BackingStoreFuncs.SaveAreas = nxagentSaveAreas;
+ pScreen -> BackingStoreFuncs.RestoreAreas = nxagentRestoreAreas;
+ pScreen -> BackingStoreFuncs.SetClipmaskRgn = 0;
+ pScreen -> BackingStoreFuncs.GetImagePixmap = 0;
+ pScreen -> BackingStoreFuncs.GetSpansPixmap = 0;
+
+ miInitializeBackingStore(pScreen);
+ }
+
+ /*
+ * OS layer procedures.
+ */
+
+ pScreen->BlockHandler = (ScreenBlockHandlerProcPtr) NoopDDA;
+ pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr) NoopDDA;
+ pScreen->blockData = NULL;
+ pScreen->wakeupData = NULL;
+
+ #ifdef RENDER
+
+ /*
+ * Initialize picture support. This have to be
+ * placed here because miDCInitialize calls
+ * DamageSetup, that should wrap the picture
+ * screen functions. So PictureInit has to be
+ * called before.
+ */
+
+ if (nxagentRenderEnable && !nxagentReconnectTrap)
+ {
+ if (!nxagentPictureInit(pScreen, 0, 0))
+ {
+ nxagentRenderEnable = False;
+
+ return FALSE;
+ }
+
+ if (nxagentAlphaEnabled)
+ {
+ fprintf(stderr, "Info: Using alpha channel in render extension.\n");
+ }
+ }
+
+ #endif /* RENDER */
+
+ /*
+ * From misprite.c: called from device-dependent screen
+ * initialization proc after all of the function pointers
+ * have been stored in the screen structure.
+ */
+
+ miDCInitialize(pScreen, &nxagentPointerCursorFuncs);
+
+ /*
+ * Cursor Procedures.
+ */
+
+ pScreen->ConstrainCursor = nxagentConstrainCursor;
+ pScreen->CursorLimits = nxagentCursorLimits;
+ pScreen->DisplayCursor = nxagentDisplayCursor;
+ pScreen->RealizeCursor = nxagentRealizeCursor;
+ pScreen->UnrealizeCursor = nxagentUnrealizeCursor;
+ pScreen->RecolorCursor = nxagentRecolorCursor;
+ pScreen->SetCursorPosition = nxagentSetCursorPosition;
+
+ #define POSITION_OFFSET (pScreen->myNum * (nxagentOption(Width) + \
+ nxagentOption(Height)) / 32)
+ }
+
+ #ifdef TEST
+ nxagentPrintAgentGeometry(NULL, "nxagentOpenScreen:");
+ #endif
+
+ if (nxagentDoFullGeneration == 1 ||
+ nxagentReconnectTrap == 1)
+ {
+ valuemask = CWBackPixel | CWEventMask | CWColormap |
+ (nxagentOption(AllScreens) == 1 ? CWOverrideRedirect : 0);
+
+ attributes.background_pixel = nxagentBlackPixel;
+
+ nxagentGetDefaultEventMask((Mask*)&attributes.event_mask);
+
+ attributes.colormap = nxagentDefaultVisualColormap(nxagentDefaultVisual(pScreen));
+
+ if (nxagentOption(AllScreens) == 1)
+ {
+ attributes.override_redirect = True;
+ }
+
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ if (nxagentReconnectTrap)
+ {
+ /*
+ * We need to disable the host's screensaver or
+ * it will otherwise grab the screen even if it
+ * is under agent's control.
+ */
+
+ XSetScreenSaver(nxagentDisplay, 0, 0, DefaultExposures, DefaultBlanking);
+ }
+ }
+
+ /*
+ * This would be used when running agent
+ * embedded into another X window.
+ */
+
+ if (nxagentParentWindow != 0)
+ {
+ nxagentDefaultWindows[pScreen->myNum] = nxagentParentWindow;
+
+ nxagentGetDefaultEventMask(&mask);
+
+ XSelectInput(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], mask);
+ }
+ else
+ {
+ /*
+ * Create any top-level window as a child of the
+ * real root of the remote display. See also the
+ * InitRootWindow() procedure and the function
+ * handling the splash screen.
+ */
+
+ if (nxagentOption(Rootless) == True)
+ {
+ nxagentDefaultWindows[pScreen->myNum] = DefaultRootWindow(nxagentDisplay);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Using root window id [%ld].\n",
+ nxagentDefaultWindows[pScreen->myNum]);
+ #endif
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Going to create new default window.\n");
+ #endif
+
+ nxagentDefaultWindows[pScreen->myNum] =
+ XCreateWindow(nxagentDisplay,
+ DefaultRootWindow(nxagentDisplay),
+ nxagentOption(X) + POSITION_OFFSET,
+ nxagentOption(Y) + POSITION_OFFSET,
+ nxagentOption(Width),
+ nxagentOption(Height),
+ nxagentOption(BorderWidth),
+ pScreen->rootDepth,
+ InputOutput,
+ nxagentDefaultVisual(pScreen),
+ valuemask, &attributes);
+
+ if (nxagentOption(Rootless) == 0)
+ {
+ valuemask = CWEventMask;
+ mask = PointerMotionMask;
+ attributes.event_mask = mask;
+
+ nxagentInputWindows[pScreen -> myNum] =
+ XCreateWindow(nxagentDisplay,
+ nxagentDefaultWindows[pScreen -> myNum],
+ 0, 0,
+ nxagentOption(Width),
+ nxagentOption(Height),
+ 0, 0, InputOnly,
+ nxagentDefaultVisual(pScreen),
+ valuemask , &attributes);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Created new default window with id [%ld].\n",
+ nxagentDefaultWindows[pScreen->myNum]);
+ #endif
+
+ if (nxagentOption(Fullscreen))
+ {
+ nxagentFullscreenWindow = nxagentDefaultWindows[pScreen->myNum];
+ }
+
+ if (nxagentIpaq)
+ {
+ XWindowChanges ch;
+ unsigned int ch_mask;
+
+ ch.stack_mode = Below;
+ ch_mask = CWStackMode;
+
+ XConfigureWindow(nxagentDisplay, nxagentFullscreenWindow, ch_mask, &ch);
+ }
+ }
+
+ if (nxagentOption(Fullscreen))
+ {
+ /*
+ * FIXME: Do we still need to set this property?
+ */
+
+ if (nxagentAtoms[8] != 0)
+ {
+ XChangeProperty(nxagentDisplay,
+ nxagentDefaultWindows[pScreen->myNum],
+ nxagentAtoms[8], /* NX_AGENT_SIGNATURE */
+ XA_STRING,
+ 8,
+ PropModeReplace,
+ (unsigned char*) "X-AGENT",
+ strlen("X-AGENT"));
+ }
+
+ nxagentGetDefaultEventMask(&mask);
+
+ XSelectInput(nxagentDisplay, nxagentFullscreenWindow, mask);
+ }
+
+ sizeHints.flags = PPosition | PMinSize | PMaxSize;
+ sizeHints.x = nxagentOption(X) + POSITION_OFFSET;
+ sizeHints.y = nxagentOption(Y) + POSITION_OFFSET;
+ sizeHints.min_width = MIN_NXAGENT_WIDTH;
+ sizeHints.min_height = MIN_NXAGENT_HEIGHT;
+
+ sizeHints.width = nxagentOption(RootWidth);
+ sizeHints.height = nxagentOption(RootHeight);
+
+ if (nxagentOption(DesktopResize) == 1 || nxagentOption(Fullscreen) == 1)
+ {
+ sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ }
+ else
+ {
+ sizeHints.max_width = nxagentOption(RootWidth);
+ sizeHints.max_height = nxagentOption(RootHeight);
+ }
+
+ if (nxagentUserGeometry.flag & XValue || nxagentUserGeometry.flag & YValue)
+ sizeHints.flags |= USPosition;
+ if (nxagentUserGeometry.flag & WidthValue || nxagentUserGeometry.flag & HeightValue)
+ sizeHints.flags |= USSize;
+
+ XSetStandardProperties(nxagentDisplay,
+ nxagentDefaultWindows[pScreen->myNum],
+ nxagentWindowName,
+ nxagentWindowName,
+ nxagentIconPixmap,
+ argv, argc, &sizeHints);
+
+ wmHints.icon_pixmap = nxagentIconPixmap;
+
+ if (useXpmIcon)
+ {
+ wmHints.icon_mask = nxagentIconShape;
+ wmHints.flags = IconPixmapHint | IconMaskHint;
+ }
+ else
+ {
+ wmHints.flags = IconPixmapHint;
+ }
+
+ XSetWMHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &wmHints);
+
+ /*
+ * Clear the window but let it unmapped. We'll map it
+ * at the time the we'll initialize our screen root
+ * and only if we are not running in rootless mode.
+ */
+
+ XClearWindow(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum]);
+
+ if (nxagentOption(AllScreens))
+ {
+ if (nxagentReconnectTrap)
+ {
+ XGrabKeyboard(nxagentDisplay, nxagentFullscreenWindow, True, GrabModeAsync,
+ GrabModeAsync, CurrentTime);
+ }
+
+ nxagentIconWindow = nxagentCreateIconWindow();
+ }
+ else
+ {
+ nxagentIconWindow = 0;
+ }
+
+ /*
+ * When we don't have window manager we grab keyboard
+ * to let nxagent get keyboard events.
+ */
+
+ if (!nxagentWMIsRunning && !nxagentOption(Fullscreen))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: No window manager, we call XGrabKeyboard.\n");
+ #endif
+
+ XGrabKeyboard(nxagentDisplay, RootWindow (nxagentDisplay, 0), True, GrabModeAsync,
+ GrabModeAsync, CurrentTime);
+ }
+ }
+
+ if (!nxagentCreateDefaultColormap(pScreen))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentOpenScreen: Failed to create default colormap for screen.\n");
+ #endif
+
+ return False;
+ }
+
+ /*
+ * The purpose of this check is to verify if there
+ * is a window manager running. Unfortunately due
+ * to the way we manage the intern atoms call, the
+ * atom will always exist.
+ */
+
+ if (nxagentWMIsRunning)
+ {
+ XlibAtom deleteWMatom = nxagentAtoms[2]; /* WM_DELETE_WINDOW */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Found WM, delete window atom [%ld].\n",
+ deleteWMatom);
+ #endif
+
+ if (nxagentOption(Rootless) == False)
+ {
+ /*
+ * Set the WM_DELETE_WINDOW protocol for the main agent
+ * window and, if we are in fullscreen mode, include the
+ * icon window.
+ */
+
+ XSetWMProtocols(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &deleteWMatom, 1);
+ }
+ else
+ {
+ /*
+ * We need to register the ICCCM WM_DELETE_WINDOW
+ * protocol for any top-level window or the agent
+ * will be killed if any window is closed.
+ */
+
+ XSetWMProtocols(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &deleteWMatom, 1);
+
+ #ifdef TEST
+ fprintf(stderr, "Warning: Not setting the WM_DELETE_WINDOW protocol.\n");
+ #endif
+ }
+ }
+ else
+ {
+ /*
+ * We should always enable the configuration of the
+ * remote X server's devices if we are running full-
+ * screen and there is no WM running.
+ */
+
+ if (nxagentOption(Fullscreen))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: WARNING! Forcing propagation of device control changes.\n");
+ #endif
+
+ nxagentChangeOption(DeviceControl, True);
+ }
+ }
+
+ /*
+ * Inform the user whether the agent's clients will
+ * be able to change the real X server's keyboard
+ * and pointer settings.
+ */
+
+ if (nxagentOption(DeviceControl) == False)
+ {
+ fprintf(stderr, "Info: Not using local device configuration changes.\n");
+ }
+ else
+ {
+ fprintf(stderr, "Info: Using local device configuration changes.\n");
+ }
+
+ #ifdef RENDER
+
+ /*
+ * if (nxagentRenderEnable && !nxagentReconnectTrap)
+ * {
+ * if (!nxagentPictureInit(pScreen, 0, 0))
+ * {
+ * nxagentRenderEnable = False;
+ *
+ * return FALSE;
+ * }
+ *
+ * if (nxagentAlphaEnabled)
+ * {
+ * fprintf(stderr, "Info: Using alpha channel in render extension.\n");
+ * }
+ * }
+ */
+
+ #endif /* RENDER */
+
+ /*
+ * Check if the composite extension is
+ * supported on the remote display and
+ * prepare the agent for its use.
+ */
+
+ nxagentCompositeExtensionInit();
+
+
+ #ifdef NXAGENT_TIMESTAMP
+
+ {
+ extern unsigned long startTime;
+
+ fprintf(stderr, "Screen: open screen finished, time is [%d] milliseconds.\n",
+ GetTimeInMillis() - startTime);
+ }
+
+ #endif
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentOpenScreen: Watchpoint 8.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+#1 U 2 1 5344 bits (1 KB) -> 2344 bits (0 KB) -> 2672/1 -> 1172/1 = 2.280:1
+#16 11 2816 bits (0 KB) -> 197 bits (0 KB) -> 256/1 -> 18/1 = 14.294:1
+#91 1 16640 bits (2 KB) -> 12314 bits (2 KB) -> 16640/1 -> 12314/1 = 1.351:1
+#98 2 512 bits (0 KB) -> 57 bits (0 KB) -> 256/1 -> 28/1 = 8.982:1
+*/
+
+ sleep(30);
+
+ #endif
+
+ return True;
+}
+
+Bool nxagentCloseScreen(int index, ScreenPtr pScreen)
+{
+ int i;
+
+ for (i = 0; i < pScreen->numDepths; i++)
+ {
+ xfree(pScreen->allowedDepths[i].vids);
+ }
+
+ /*
+ * Free the frame buffer.
+ */
+
+ xfree(((PixmapPtr)pScreen -> devPrivate) -> devPrivate.ptr);
+
+ xfree(pScreen->allowedDepths);
+ xfree(pScreen->visuals);
+ xfree(pScreen->devPrivate);
+
+ /*
+ * Reset the geometry and alpha information
+ * used by proxy to unpack the packed images.
+ */
+
+ nxagentResetVisualCache();
+ nxagentResetAlphaCache();
+ nxagentReleaseAllSplits();
+
+ /*
+ * The assumption is that all X resources will be
+ * destroyed upon closing the display connection.
+ * There is no need to generate extra protocol.
+ */
+
+ return True;
+}
+
+/*
+ * This function comes from the xfree86 Xserver.
+ */
+
+static void nxagentSetRootClip (ScreenPtr pScreen, Bool enable)
+{
+ WindowPtr pWin = WindowTable[pScreen->myNum];
+ WindowPtr pChild;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ Bool anyMarked = FALSE;
+ RegionPtr pOldClip = NULL, bsExposed;
+#ifdef DO_SAVE_UNDERS
+ Bool dosave = FALSE;
+#endif
+ WindowPtr pLayerWin;
+ BoxRec box;
+
+ if (WasViewable)
+ {
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+ {
+ (void) (*pScreen->MarkOverlappedWindows)(pChild,
+ pChild,
+ &pLayerWin);
+ }
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ if (pWin->valdata)
+ {
+ if (HasBorder (pWin))
+ {
+ RegionPtr borderVisible;
+
+ borderVisible = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_SUBTRACT(pScreen, borderVisible,
+ &pWin->borderClip, &pWin->winSize);
+ pWin->valdata->before.borderVisible = borderVisible;
+ }
+ pWin->valdata->before.resized = TRUE;
+ }
+ }
+
+ /*
+ * Use REGION_BREAK to avoid optimizations in ValidateTree
+ * that assume the root borderClip can't change well, normally
+ * it doesn't...)
+ */
+ if (enable)
+ {
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+ REGION_INIT (pScreen, &pWin->winSize, &box, 1);
+ REGION_INIT (pScreen, &pWin->borderSize, &box, 1);
+ if (WasViewable)
+ REGION_RESET(pScreen, &pWin->borderClip, &box);
+ pWin->drawable.width = pScreen->width;
+ pWin->drawable.height = pScreen->height;
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+ else
+ {
+ REGION_EMPTY(pScreen, &pWin->borderClip);
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+
+ ResizeChildrenWinSize (pWin, 0, 0, 0, 0);
+
+ if (WasViewable)
+ {
+ if (pWin->backStorage)
+ {
+ pOldClip = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, pOldClip, &pWin->clipList);
+ }
+
+ if (pWin->firstChild)
+ {
+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild,
+ pWin->firstChild,
+ (WindowPtr *)NULL);
+ }
+ else
+ {
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ }
+
+#ifdef DO_SAVE_UNDERS
+ if (DO_SAVE_UNDERS(pWin))
+ {
+ dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin);
+ }
+#endif /* DO_SAVE_UNDERS */
+
+ if (anyMarked)
+ (*pScreen->ValidateTree)(pWin, NullWindow, VTOther);
+ }
+
+ if (pWin->backStorage && pOldClip &&
+ ((pWin->backingStore == Always) || WasViewable))
+ {
+ if (!WasViewable)
+ pOldClip = &pWin->clipList; /* a convenient empty region */
+ bsExposed = (*pScreen->TranslateBackingStore)
+ (pWin, 0, 0, pOldClip,
+ pWin->drawable.x, pWin->drawable.y);
+ if (WasViewable)
+ REGION_DESTROY(pScreen, pOldClip);
+ if (bsExposed)
+ {
+ RegionPtr valExposed = NullRegion;
+
+ if (pWin->valdata)
+ valExposed = &pWin->valdata->after.exposed;
+ (*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
+ if (valExposed)
+ REGION_EMPTY(pScreen, valExposed);
+ REGION_DESTROY(pScreen, bsExposed);
+ }
+ }
+ if (WasViewable)
+ {
+ if (anyMarked)
+ (*pScreen->HandleExposures)(pWin);
+#ifdef DO_SAVE_UNDERS
+ if (dosave)
+ (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin);
+#endif /* DO_SAVE_UNDERS */
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+ FlushAllOutput ();
+}
+
+Bool nxagentResizeScreen(ScreenPtr pScreen, int width, int height,
+ int mmWidth, int mmHeight)
+{
+ BoxRec box;
+ XSizeHints sizeHints;
+ PixmapPtr pPixmap;
+ char *fbBits;
+
+ int oldWidth;
+ int oldHeight;
+ int oldMmWidth;
+ int oldMmHeight;
+
+ #ifdef TEST
+ nxagentPrintAgentGeometry("Before Resize Screen", "nxagentResizeScreen:");
+ #endif
+
+ /*
+ * Change screen properties.
+ */
+
+ oldWidth = pScreen -> width;
+ oldHeight = pScreen -> height;
+ oldMmWidth = pScreen -> mmWidth;
+ oldMmHeight = pScreen -> mmHeight;
+
+ pScreen -> width = width;
+ pScreen -> height = height;
+
+ /*
+ * Compute screen dimensions if they aren't given.
+ */
+
+ if (mmWidth == 0)
+ {
+ mmWidth = (width * 254 + monitorResolution * 5) / (monitorResolution * 10);
+
+ if (mmWidth < 1)
+ {
+ mmWidth = 1;
+ }
+ }
+
+ if (mmHeight == 0)
+ {
+ mmHeight = (height * 254 + monitorResolution * 5) / (monitorResolution * 10);
+
+ if (mmHeight < 1)
+ {
+ mmHeight = 1;
+ }
+ }
+
+ pScreen -> mmWidth = mmWidth;
+ pScreen -> mmHeight = mmHeight;
+
+ pPixmap = fbGetScreenPixmap(pScreen);
+
+ if ((fbBits = realloc(pPixmap -> devPrivate.ptr, PixmapBytePad(width, pScreen->rootDepth) *
+ height * BitsPerPixel(pScreen->rootDepth) / 8)) == NULL)
+ {
+ pScreen -> width = oldWidth;
+ pScreen -> height = oldHeight;
+ pScreen -> mmWidth = oldMmWidth;
+ pScreen -> mmHeight = oldMmHeight;
+
+ goto nxagentResizeScreenError;
+ }
+
+ if (!miModifyPixmapHeader(pPixmap, width, height,
+ pScreen->rootDepth, BitsPerPixel(pScreen->rootDepth),
+ PixmapBytePad(width,
+ pScreen->rootDepth), fbBits))
+ {
+/*
+FIXME: We should try to restore the previously
+ reallocated frame buffer pixmap.
+*/
+
+ pScreen -> width = oldWidth;
+ pScreen -> height = oldHeight;
+ pScreen -> mmWidth = oldMmWidth;
+ pScreen -> mmHeight = oldMmHeight;
+
+ goto nxagentResizeScreenError;
+ }
+
+ nxagentChangeOption(RootWidth, width);
+ nxagentChangeOption(RootHeight, height);
+
+ if (nxagentOption(Fullscreen))
+ {
+ nxagentChangeOption(RootX, (nxagentOption(Width) -
+ nxagentOption(RootWidth)) / 2);
+ nxagentChangeOption(RootY, (nxagentOption(Height) -
+ nxagentOption(RootHeight)) / 2);
+ }
+ else
+ {
+ nxagentChangeOption(RootX, 0);
+ nxagentChangeOption(RootY, 0);
+ }
+
+ nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth));
+ nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight));
+
+ /*
+ * Change agent window size and size hints.
+ */
+
+ if ((nxagentOption(Fullscreen) == 0 && nxagentOption(AllScreens) == 0))
+ {
+ sizeHints.flags = PPosition | PMinSize | PMaxSize;
+ sizeHints.x = nxagentOption(X);
+ sizeHints.y = nxagentOption(Y);
+
+ sizeHints.min_width = MIN_NXAGENT_WIDTH;
+ sizeHints.min_height = MIN_NXAGENT_HEIGHT;
+ sizeHints.width = width;
+ sizeHints.height = height;
+
+ if (nxagentOption(DesktopResize) == 1)
+ {
+ sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ }
+ else
+ {
+ sizeHints.max_width = nxagentOption(RootWidth);
+ sizeHints.max_height = nxagentOption(RootHeight);
+ }
+
+ if (nxagentUserGeometry.flag & XValue || nxagentUserGeometry.flag & YValue)
+ {
+ sizeHints.flags |= USPosition;
+ }
+
+ if (nxagentUserGeometry.flag & WidthValue || nxagentUserGeometry.flag & HeightValue)
+ {
+ sizeHints.flags |= USSize;
+ }
+
+ XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &sizeHints);
+
+ XResizeWindow(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], width, height);
+
+ if (nxagentOption(Rootless) == 0)
+ {
+ XResizeWindow(nxagentDisplay, nxagentInputWindows[pScreen -> myNum], width, height);
+ }
+ }
+
+ /*
+ * Set properties for the agent root window.
+ */
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = width;
+ box.y2 = height;
+
+ WindowTable[pScreen -> myNum] -> drawable.width = width;
+ WindowTable[pScreen -> myNum] -> drawable.height = height;
+ WindowTable[pScreen -> myNum] -> drawable.x = 0;
+ WindowTable[pScreen -> myNum] -> drawable.y = 0;
+
+ REGION_INIT(pScreen, &WindowTable[pScreen -> myNum] -> borderSize, &box, 1);
+ REGION_INIT(pScreen, &WindowTable[pScreen -> myNum] -> winSize, &box, 1);
+ REGION_INIT(pScreen, &WindowTable[pScreen -> myNum] -> clipList, &box, 1);
+ REGION_INIT(pScreen, &WindowTable[pScreen -> myNum] -> borderClip, &box, 1);
+
+ (*pScreen -> PositionWindow)(WindowTable[pScreen -> myNum], 0, 0);
+
+ nxagentSetRootClip(pScreen, 1);
+
+ XMoveWindow(nxagentDisplay, nxagentWindow(WindowTable[0]),
+ nxagentOption(RootX), nxagentOption(RootY));
+
+ nxagentMoveViewport(pScreen, 0, 0);
+
+ /*
+ * Update pointer bounds.
+ */
+
+ ScreenRestructured(pScreen);
+
+ #ifdef TEST
+ nxagentPrintAgentGeometry("After Resize Screen", "nxagentResizeScreen:");
+ #endif
+
+ nxagentSetPrintGeometry(pScreen -> myNum);
+
+ return 1;
+
+nxagentResizeScreenError:
+
+ return 0;
+}
+
+void nxagentShadowSetRatio(float floatXRatio, float floatYRatio)
+{
+ int intXRatio;
+ int intYRatio;
+
+ if (floatXRatio == 0)
+ {
+ floatXRatio = 1.0;
+ }
+
+ if (floatYRatio == 0)
+ {
+ floatYRatio = 1.0;
+ }
+
+ intXRatio = floatXRatio * (1 << PRECISION);
+ intYRatio = floatYRatio * (1 << PRECISION);
+
+ nxagentChangeOption(FloatXRatio, floatXRatio);
+ nxagentChangeOption(FloatYRatio, floatYRatio);
+
+ nxagentChangeOption(XRatio, intXRatio);
+ nxagentChangeOption(YRatio, intYRatio);
+
+ #ifdef TEST
+ fprintf(stderr, "Info: Using X ratio [%f] Y ratio [%f].\n",
+ nxagentOption(FloatXRatio), nxagentOption(FloatYRatio));
+ #endif
+}
+
+void nxagentShadowSetWindowsSize(void)
+{
+ XResizeWindow(nxagentDisplay, nxagentDefaultWindows[0],
+ nxagentOption(Width), nxagentOption(Height));
+
+ XMoveResizeWindow(nxagentDisplay, nxagentInputWindows[0], 0, 0,
+ nxagentOption(Width), nxagentOption(Height));
+}
+
+void nxagentShadowSetWindowOptions(void)
+{
+ nxagentChangeOption(RootWidth, nxagentScale(nxagentShadowWidth, nxagentOption(XRatio)));
+ nxagentChangeOption(RootHeight, nxagentScale(nxagentShadowHeight, nxagentOption(YRatio)));
+
+ nxagentChangeOption(SavedRootWidth, nxagentOption(RootWidth));
+ nxagentChangeOption(SavedRootHeight, nxagentOption(RootHeight));
+
+ nxagentChangeOption(RootX, (nxagentOption(Width) - nxagentOption(RootWidth)) >> 1);
+ nxagentChangeOption(RootY, (nxagentOption(Height) - nxagentOption(RootHeight)) >> 1);
+}
+
+int nxagentShadowInit(ScreenPtr pScreen, WindowPtr pWin)
+{
+ int i;
+ char *layout = NULL;
+ extern char *nxagentKeyboard;
+ XlibGC gc;
+ XGCValues value;
+
+ #ifndef __CYGWIN32__
+
+ Atom nxagentShadowAtom;
+
+ int fd;
+
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "Info: Init shadow session. nxagentDisplayName [%s] "
+ "nxagentDisplay [%p] nxagentShadowDisplayName [%s].\n",
+ nxagentDisplayName, (void *) nxagentDisplay,
+ nxagentShadowDisplayName);
+ #endif
+
+ if (nxagentKeyboard != NULL)
+ {
+ for (i = 0; nxagentKeyboard[i] != '/' && nxagentKeyboard[i] != 0; i++);
+
+ if(nxagentKeyboard[i] == 0 || nxagentKeyboard[i + 1] == 0 || i == 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr,"WARNING! Wrong keyboard type: %s.\n", nxagentKeyboard);
+ #endif
+ }
+ else
+ {
+ layout = malloc(strlen(&nxagentKeyboard[i + 1]) + 1);
+
+ strcpy(layout, &nxagentKeyboard[i + 1]);
+ }
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShadowInit: Setting the master uid [%d].\n",
+ nxagentShadowUid);
+ #endif
+
+#if !defined (__CYGWIN32__) && !defined (WIN32)
+
+ if (nxagentShadowUid != -1)
+ {
+ NXShadowSetDisplayUid(nxagentShadowUid);
+ }
+
+ if (nxagentOption(UseDamage) == 0)
+ {
+ NXShadowDisableDamage();
+ }
+
+#endif
+
+ if (NXShadowCreate(nxagentDisplay, layout, nxagentShadowDisplayName,
+ (void *) &nxagentShadowDisplay) != 1)
+ {
+ #ifdef PANIIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Failed to initialize shadow "
+ "display [%s].\n", nxagentShadowDisplayName);
+ #endif
+
+ return -1;
+ }
+
+ /*
+ * The shadow nxagent sets the _NX_SHADOW
+ * property on the master X server root
+ * window in order to notify its presence.
+ */
+
+ #ifndef __CYGWIN__
+
+ nxagentShadowAtom = XInternAtom(nxagentShadowDisplay, "_NX_SHADOW", False);
+
+ XChangeProperty(nxagentShadowDisplay, DefaultRootWindow(nxagentShadowDisplay),
+ nxagentShadowAtom, XA_STRING, 8, PropModeReplace, NULL, 0);
+ #endif
+
+ if (NXShadowAddUpdaterDisplay(nxagentDisplay, &nxagentShadowWidth,
+ &nxagentShadowHeight, &nxagentMasterDepth) == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Failed to add display [%s].\n",
+ nxagentDisplayName);
+ #endif
+
+ return -1;
+ }
+
+ #ifndef __CYGWIN32__
+
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ nxagentShadowSetRatio(WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 1.0 / nxagentShadowWidth,
+ HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 1.0 / nxagentShadowHeight);
+ }
+ else if (nxagentUserGeometry.flag != 0)
+ {
+ nxagentShadowSetRatio(nxagentOption(RootWidth) * 1.0 / nxagentShadowWidth,
+ nxagentOption(RootHeight) * 1.0 / nxagentShadowHeight);
+ }
+
+ if (DefaultVisualOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) ->
+ class != TrueColor)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! The visual class of the remote "
+ "X server is not TrueColor.\n");
+ #endif
+
+ return -1;
+ }
+
+ if (DefaultVisualOfScreen(DefaultScreenOfDisplay(nxagentShadowDisplay)) ->
+ class != TrueColor)
+ {
+ #ifdef PANIC
+
+ const char *className;
+
+ switch (DefaultVisualOfScreen(DefaultScreenOfDisplay(nxagentShadowDisplay)) -> class)
+ {
+ case StaticGray:
+ {
+ className = "StaticGray";
+
+ break;
+ }
+ case StaticColor:
+ {
+ className = "StaticColor";
+
+ break;
+ }
+ case PseudoColor:
+ {
+ className = "PseudoColor";
+
+ break;
+ }
+ case DirectColor:
+ {
+ className = "DirectColor";
+
+ break;
+ }
+ case GrayScale:
+ {
+ className = "GrayScale";
+
+ break;
+ }
+ default:
+ {
+ className = "";
+
+ break;
+ }
+ }
+
+ fprintf(stderr, "nxagentShadowInit: PANIC! Cannot shadow the display. "
+ "%s visual class is not supported. Only TrueColor visuals "
+ "are supported.\n", className);
+
+ #endif /* #endif PANIC */
+
+ return -1;
+ }
+
+ #endif
+
+ nxagentShadowDepth = pScreen -> rootDepth;
+
+ switch (nxagentMasterDepth)
+ {
+ case 32:
+ case 24:
+ {
+ if (nxagentShadowDepth == 16)
+ {
+ nxagentCheckDepth = 1;
+ }
+ else if (nxagentShadowDepth == 8)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Unable to shadow a %d bit "
+ "display with a 8 bit screen depth.\n", nxagentMasterDepth);
+ #endif
+
+ return -1;
+ }
+
+ nxagentBppMaster = 4;
+
+ break;
+ }
+ case 16:
+ {
+ if (nxagentShadowDepth > 16)
+ {
+ nxagentCheckDepth = 1;
+ }
+ else if (nxagentShadowDepth == 8)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Unable to shadow a 16 bit "
+ "display with a 8 bit screen depth.\n");
+ #endif
+
+ return -1;
+ }
+
+ nxagentBppMaster = 2;
+
+ break;
+ }
+ case 8:
+ {
+ if (nxagentShadowDepth != 8)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Unable to shadow a 8 bit "
+ "display with a %d bit screen depth.\n", nxagentShadowDepth);
+ #endif
+
+ return -1;
+ }
+
+ nxagentBppMaster = 1;
+
+ break;
+ }
+ default:
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! The depth is not 32, 24, 16 or 8 bit.\n");
+ #endif
+
+ return -1;
+ }
+ }
+
+ if (nxagentShadowDepth >= 24)
+ {
+ nxagentBppShadow = 4;
+ }
+ else if (nxagentShadowDepth == 16)
+ {
+ nxagentBppShadow = 2;
+ }
+ else if (nxagentShadowDepth == 8)
+ {
+ nxagentBppShadow = 1;
+ }
+
+#if !defined(__CYGWIN__)
+
+ imageByteOrder = nxagentShadowDisplay -> byte_order;
+
+ fd = XConnectionNumber(nxagentShadowDisplay);
+
+ nxagentShadowXConnectionNumber = fd;
+
+#endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentAddXConnection: Adding the X connection [%d] "
+ "to the device set.\n", fd);
+ #endif
+
+ AddEnabledDevice(nxagentShadowXConnectionNumber);
+
+ accessPixmapID = FakeClientID(serverClient -> index);
+
+ AddResource(accessPixmapID, RT_PIXMAP, (pointer)nxagentShadowPixmapPtr);
+
+ accessWindowID = FakeClientID(serverClient -> index);
+
+ AddResource(accessWindowID, RT_WINDOW, (pointer)nxagentShadowWindowPtr);
+
+ nxagentResizeScreen(pScreen, nxagentShadowWidth, nxagentShadowHeight, pScreen -> mmWidth, pScreen -> mmHeight);
+
+ nxagentShadowCreateMainWindow(pScreen, pWin, nxagentShadowWidth, nxagentShadowHeight);
+
+ if (nxagentRemoteMajor <= 3)
+ {
+ nxagentShadowSetWindowsSize();
+
+ nxagentSetWMNormalHints(0);
+ }
+
+ XMapWindow(nxagentDisplay, nxagentDefaultWindows[0]);
+
+ /*
+ * Clean up the main window.
+ */
+
+ value.foreground = 0x00000000;
+ value.background = 0x00000000;
+ value.plane_mask = 0xffffffff;
+ value.fill_style = FillSolid;
+
+ gc = XCreateGC(nxagentDisplay, nxagentPixmap(nxagentShadowPixmapPtr), GCBackground |
+ GCForeground | GCFillStyle | GCPlaneMask, &value);
+
+ XFillRectangle(nxagentDisplay, nxagentPixmap(nxagentShadowPixmapPtr), gc, 0, 0,
+ nxagentShadowWidth, nxagentShadowHeight);
+
+ XFreeGC(nxagentDisplay, gc);
+
+ REGION_INIT(pScreen, &nxagentShadowUpdateRegion, (BoxRec*)NULL, 1);
+
+ return 0;
+}
+
+int nxagentShadowCreateMainWindow(ScreenPtr pScreen, WindowPtr pWin, int width, int height)
+{
+ XWindowChanges changes;
+ Mask mask,maskb;
+ XID values[4], *vlist;
+ int error;
+ XID xid;
+
+ nxagentShadowWidth = width;
+ nxagentShadowHeight = height;
+
+ NXShadowUpdateBuffer((void *)&nxagentShadowBuffer);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowCreateMainWindow: Update frame buffer [%p].\n", nxagentShadowBuffer);
+ #endif
+
+ nxagentShadowSetWindowOptions();
+
+ if (nxagentShadowPixmapPtr != NULL)
+ {
+ nxagentDestroyPixmap(nxagentShadowPixmapPtr);
+ }
+
+ if (nxagentShadowWindowPtr != NULL)
+ {
+ DeleteWindow(nxagentShadowWindowPtr, accessWindowID);
+ }
+
+ nxagentShadowPixmapPtr = nxagentCreatePixmap(pScreen, nxagentShadowWidth, nxagentShadowHeight, nxagentShadowDepth);
+
+ if (nxagentShadowPixmapPtr)
+ {
+ ChangeResourceValue(accessPixmapID, RT_PIXMAP, (pointer) nxagentShadowPixmapPtr);
+ nxagentShadowPixmapPtr -> drawable.id = accessPixmapID;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowCreateMainWindow: nxagentShadowPixmapPtr [%p] PixmapM -> drawable.id [%lu].\n",
+ (void *)nxagentShadowPixmapPtr, nxagentShadowPixmapPtr -> drawable.id);
+ fprintf(stderr, "nxagentShadowCreateMainWindow: Create pixmap with width [%d] height [%d] depth [%d].\n",
+ nxagentShadowWidth, nxagentShadowHeight, (int)nxagentShadowDepth);
+ #endif
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowCreateMainWindow: PANIC! Failed to create pixmap with width [%d] height [%d] depth [%d].\n",
+ nxagentShadowWidth, nxagentShadowHeight, (int)nxagentShadowDepth);
+ #endif
+ }
+
+ XFreePixmap(nxagentDisplay, nxagentPixmap(nxagentVirtualPixmap(nxagentShadowPixmapPtr)));
+
+ xid = XCreatePixmap(nxagentDisplay, nxagentDefaultWindows[0],
+ nxagentScale(nxagentShadowWidth, nxagentOption(XRatio)),
+ nxagentScale(nxagentShadowHeight, nxagentOption(YRatio)), nxagentShadowDepth);
+
+ nxagentPixmap(nxagentVirtualPixmap(nxagentShadowPixmapPtr)) = xid;
+
+ nxagentPixmap(nxagentRealPixmap(nxagentShadowPixmapPtr)) = xid;
+
+ if (nxagentShadowGCPtr != NULL)
+ {
+ FreeScratchGC(nxagentShadowGCPtr);
+ }
+/*
+ * FIXME: Should use CreateGC.
+ */
+ nxagentShadowGCPtr = GetScratchGC(nxagentShadowPixmapPtr -> drawable.depth, nxagentShadowPixmapPtr -> drawable.pScreen);
+
+ if (nxagentShadowGCPtr)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowCreateMainWindow: Created GC with pGC[%p]\n", nxagentShadowGCPtr);
+ #endif
+ ValidateGC((DrawablePtr)nxagentShadowPixmapPtr, nxagentShadowGCPtr);
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowCreateMainWindow: PANIC! Failed to create GC.");
+ #endif
+ }
+
+ mask = CWBackPixmap | CWEventMask | CWCursor;
+
+ nxagentGetDefaultEventMask(&maskb);
+ maskb |= ResizeRedirectMask | ExposureMask;
+
+ vlist = values;
+ *vlist++ = (XID)nxagentShadowPixmapPtr -> drawable.id;
+ *vlist++ = (XID)maskb;
+
+ *vlist = (XID)None;
+
+ nxagentShadowWindowPtr = CreateWindow(accessWindowID, pWin, 0, 0, nxagentShadowWidth,
+ nxagentShadowHeight, 0, InputOutput, mask, (XID *)values,
+ nxagentShadowDepth, serverClient, CopyFromParent, &error);
+
+ mask = CWWidth | CWHeight;
+ changes.width = nxagentScale(nxagentShadowWidth, nxagentOption(XRatio));
+ changes.height = nxagentScale(nxagentShadowHeight, nxagentOption(YRatio));
+
+ XConfigureWindow(nxagentDisplay, nxagentWindow(nxagentShadowWindowPtr), mask, &changes);
+
+ nxagentMoveViewport(pScreen, 0, 0);
+
+ if (nxagentShadowWindowPtr && !error)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowCreateMainWindow: Create window with nxagentShadowWindowPtr [%p]"
+ "nxagentShadowWindowPtr -> drawable.id [%lu].\n", (void *) nxagentShadowWindowPtr,
+ nxagentShadowWindowPtr -> drawable.id);
+
+ fprintf(stderr, "nxagentShadowCreateMainWindow: parent nxagentShadowWindowPtr [%p] parent -> drawable.id [%lu].\n",
+ (void *)nxagentShadowWindowPtr->parent, nxagentShadowWindowPtr -> parent -> drawable.id);
+
+ #endif
+
+ ChangeResourceValue(accessWindowID, RT_WINDOW, (pointer) nxagentShadowWindowPtr);
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowCreateMainWindow: PANIC! Failed to create window.\n");
+ #endif
+ }
+
+ XMapWindow(nxagentDisplay, nxagentWindow(nxagentShadowWindowPtr));
+ MapWindow(nxagentShadowWindowPtr, serverClient);
+
+ mask = CWX | CWY | CWWidth | CWHeight;
+ changes.x = nxagentOption(RootX);
+ changes.y = nxagentOption(RootY);
+ changes.width = nxagentScale(nxagentShadowWidth, nxagentOption(XRatio));
+ changes.height = nxagentScale(nxagentShadowHeight, nxagentOption(YRatio));
+ XConfigureWindow(nxagentDisplay, nxagentWindow(pWin), mask, &changes);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowCreateMainWindow: Completed mapping of Access window.\n");
+ #endif
+
+ return 0;
+}
+
+int nxagentShadowSendUpdates(int *suspended)
+{
+ *suspended = 0;
+
+ if (REGION_NIL(&nxagentShadowUpdateRegion) == 1)
+ {
+ return 0;
+ }
+
+ nxagentMarkCorruptedRegion((DrawablePtr)nxagentShadowPixmapPtr, &nxagentShadowUpdateRegion);
+
+ REGION_EMPTY(nxagentShadowPixmapPtr -> drawable.pScreen, &nxagentShadowUpdateRegion);
+
+ return 1;
+}
+
+int nxagentShadowPoll(PixmapPtr nxagentShadowPixmapPtr, GCPtr nxagentShadowGCPtr,
+ unsigned char nxagentShadowDepth, int nxagentShadowWidth,
+ int nxagentShadowHeight, char *nxagentShadowBuffer, int *changed, int *suspended)
+{
+ int x, y, y2, n, c, line;
+ int result;
+ long numRects;
+ unsigned int width, height, length;
+ char *tBuffer = NULL;
+ char *iBuffer, *ptBox;
+ BoxRec *pBox;
+ RegionRec updateRegion;
+ RegionRec tempRegion;
+ BoxRec box;
+ int overlap;
+
+
+ REGION_NULL(pScreen, &updateRegion);
+
+ REGION_NULL(pScreen, &tempRegion);
+
+#ifdef __CYGWIN32__
+
+ if (NXShadowCaptureCursor(nxagentWindow(nxagentShadowWindowPtr),
+ nxagentShadowWindowPtr -> drawable.pScreen -> visuals) == -1)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentShadowPoll: Failed to capture cursor.\n");
+ #endif
+ }
+
+#endif
+
+ result = NXShadowHasChanged(nxagentUserInput, NULL, suspended);
+
+ *changed = result;
+
+ if (result == 1)
+ {
+ if (nxagentWMPassed == 0)
+ {
+ nxagentRemoveSplashWindow(NULL);
+ }
+
+ NXShadowExportChanges(&numRects, &ptBox);
+ pBox = (BoxRec *)ptBox;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowPoll: nRects[%ld],pBox[%p] depth[%d].\n", numRects, pBox, nxagentShadowDepth);
+ #endif
+
+ for (n = 0; n < numRects; n++)
+ {
+ /*
+ * The BoxRec struct defined in the Xserver has a different
+ * variable order in comparison with the BoxRec struct in the Xlib.
+ * the second and third field are inverted.
+ */
+
+ x = pBox[n].x1;
+ y = pBox[n].x2;
+ y2 = pBox[n].y2;
+ width = pBox[n].y1 - pBox[n].x1;/* y1 = x2 */
+ height = y2 - pBox[n].x2; /* x2 = y1 */
+
+ if((x + width) > nxagentShadowWidth || (y + height) > nxagentShadowHeight)
+ {
+ /*
+ * Out of bounds. Maybe a resize of the master session is going on.
+ */
+
+ continue;
+ }
+
+ line = PixmapBytePad(width, nxagentMasterDepth);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShadowPoll: Rectangle Number[%d] - x[%d]y[%d]W[%u]H[%u].\n", n+1, x, y, width, height);
+ #endif
+
+ length = nxagentImageLength(width, height, ZPixmap, 0, nxagentMasterDepth);
+
+ if (tBuffer)
+ {
+ xfree(tBuffer);
+ }
+
+ tBuffer = xalloc(length);
+
+ if (tBuffer == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowPoll: xalloc failed.\n");
+ #endif
+
+ return -1;
+ }
+
+ iBuffer = tBuffer;
+
+ for (c = 0; c + y < y2; c++)
+ {
+ memcpy(tBuffer, nxagentShadowBuffer + x * nxagentBppMaster +
+ (y + c) * nxagentShadowWidth * nxagentBppMaster, line);
+
+ tBuffer += line;
+
+ }
+
+ tBuffer = iBuffer;
+
+#ifdef __CYGWIN32__
+ if (nxagentBppMaster == 2)
+ {
+ NXShadowCorrectColor(length, tBuffer);
+ }
+#else
+ if (nxagentCheckDepth == 1)
+ {
+ nxagentShadowAdaptDepth(width, height, line, &tBuffer);
+ }
+#endif
+
+ fbPutImage(nxagentVirtualDrawable((DrawablePtr)nxagentShadowPixmapPtr), nxagentShadowGCPtr,
+ nxagentShadowDepth, x, y, width, height, 0, ZPixmap, tBuffer);
+
+ box.x1 = x;
+ box.x2 = x + width;
+ box.y1 = y;
+ box.y2 = y + height;
+
+ REGION_INIT(pScreen, &tempRegion, &box, 1);
+
+ REGION_APPEND(pScreen, &updateRegion, &tempRegion);
+
+ REGION_UNINIT(pScreen, &tempRegion);
+
+ REGION_VALIDATE(pScreen, &updateRegion, &overlap);
+
+ REGION_UNION(pScreen, &nxagentShadowUpdateRegion, &nxagentShadowUpdateRegion, &updateRegion);
+ }
+
+ if (tBuffer)
+ {
+ xfree(tBuffer);
+ }
+
+ REGION_UNINIT(pScreen, &updateRegion);
+ }
+ else if (result == -1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowPoll: polling failed!\n");
+ #endif
+
+ usleep(50 * 1000);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+void nxagentShadowAdaptDepth(unsigned int width, unsigned int height,
+ unsigned int lineMaster, char **buffer)
+{
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ unsigned short color16 = 0;
+ unsigned char * icBuffer;
+ unsigned char * cBuffer = NULL;
+ unsigned char * tBuffer = (unsigned char *) *buffer;
+ unsigned int lineShadow;
+ unsigned int length;
+ unsigned int c;
+ unsigned int pad;
+ unsigned int color32 = 0;
+ unsigned long redMask;
+ unsigned long greenMask;
+ unsigned long blueMask;
+ Visual *pVisual;
+
+ length = nxagentImageLength(width, height, ZPixmap, 0, nxagentShadowDepth);
+
+ cBuffer = xalloc(length);
+ icBuffer = cBuffer;
+
+ pVisual = nxagentImageVisual((DrawablePtr) nxagentShadowPixmapPtr, nxagentShadowDepth);
+
+ if (pVisual == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCorrectDepthShadow: WARNING! Visual not found. Using default visual.\n");
+ #endif
+
+ pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCorrectDepthShadow: Shadow redMask [%x] greenMask[%x] blueMask[%x].\n",
+ pVisual -> red_mask, pVisual -> green_mask, pVisual -> blue_mask);
+ #endif
+
+ redMask = nxagentShadowDisplay -> screens[0].root_visual[0].red_mask;
+ greenMask = nxagentShadowDisplay -> screens[0].root_visual[0].green_mask;
+ blueMask = nxagentShadowDisplay -> screens[0].root_visual[0].blue_mask;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCorrectDepthShadow: Master redMask [%x] greenMask[%x] blueMask[%x].\n",
+ redMask, greenMask, blueMask);
+ #endif
+
+ switch(nxagentMasterDepth)
+ {
+ /*
+ * The Shadow agent has 24 bit depth.
+ */
+ case 16:
+ {
+ pad = lineMaster - nxagentBppMaster * width;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCorrectDepthShadow: line [%d] width[%d] pad[%d].\n", lineMaster, width, pad);
+ #endif
+
+ while (height > 0)
+ {
+ for (c = 0; c < width ; c++)
+ {
+ if (imageByteOrder == LSBFirst)
+ {
+ color16 = *tBuffer++;
+ color16 |= (*tBuffer << 8);
+ }
+ else
+ {
+ color16 = (*tBuffer++) << 8;
+ color16 |= *tBuffer;
+ }
+
+ blue = ((short) blueMask & color16) << 3;
+ blue |= 0x3;
+
+ if (greenMask == 0x7e0)
+ {
+ /*
+ * bit mask 5-6-5
+ */
+
+ green = ((short) greenMask & color16) >> 3;
+ green |= 0x2;
+
+ red = ((short) redMask & color16) >> 8;
+ red |= 0x3;
+ }
+ else
+ {
+ /*
+ * bit mask 5-5-5
+ */
+
+ green = ((short) greenMask & color16) >> 2;
+ green |= 0x3;
+
+ red = ((short) redMask & color16) >> 7;
+ red |= 0x3;
+ }
+
+ tBuffer++;
+
+ if (nxagentDisplay -> byte_order == LSBFirst)
+ {
+ *cBuffer++ = blue;
+ *cBuffer++ = green;
+ *cBuffer++ = red;
+ cBuffer++;
+ }
+ else
+ {
+ cBuffer++;
+ *cBuffer++ = red;
+ *cBuffer++ = green;
+ *cBuffer++ = blue;
+ }
+ }
+ tBuffer += pad;
+ height--;
+ }
+ break;
+ }
+
+ /*
+ * The Shadow agent has 16 bit depth.
+ */
+ case 24:
+ {
+ lineShadow = PixmapBytePad(width, nxagentShadowDepth);
+
+ pad = lineShadow - nxagentBppShadow * width;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCorrectDepthShadow: line [%d] width[%d] pad[%d].\n", lineShadow, width, pad);
+ #endif
+
+ while (height > 0)
+ {
+ for (c = 0; c < width; c++)
+ {
+ if (imageByteOrder == LSBFirst)
+ {
+ color32 = *tBuffer++;
+ color32 |= (*tBuffer++ << 8);
+ color32 |= (*tBuffer++ << 16);
+ tBuffer++;
+ }
+ else
+ {
+ tBuffer++;
+ color32 = (*tBuffer++ << 16);
+ color32 |= (*tBuffer++ << 8);
+ color32 |= *tBuffer++;
+ }
+
+ color16 = (color32 & (pVisual -> blue_mask << 3)) >> 3;
+
+ if (pVisual -> green_mask == 0x7e0)
+ {
+ /*
+ * bit mask 5-6-5
+ */
+ color16 |= (color32 & (pVisual -> green_mask << 5)) >> 5;
+ color16 |= (color32 & (pVisual -> red_mask << 8)) >> 8;
+ }
+ else
+ {
+ /*
+ * bit mask 5-5-5
+ */
+ color16 |= (color32 & (pVisual -> green_mask << 6)) >> 6;
+ color16 |= (color32 & (pVisual -> red_mask << 9)) >> 9;
+ }
+
+ if (nxagentDisplay -> byte_order == LSBFirst)
+ {
+ *cBuffer++ = color16 & 0xff;
+ *cBuffer++ = (color16 & 0xff00) >> 8;
+ }
+ else
+ {
+ *cBuffer++ = (color16 & 0xff00) >> 8;
+ *cBuffer++ = color16 & 0xff;
+ }
+ }
+ cBuffer += pad;
+ height--;
+ }
+ break;
+ }
+ }
+ cBuffer = (unsigned char *) *buffer;
+ *buffer = (char *) icBuffer;
+
+ if (cBuffer != NULL)
+ {
+ xfree(cBuffer);
+ }
+}
+
+#ifdef NXAGENT_ARTSD
+
+unsigned char fromHexNibble(char c)
+{
+ int uc = (unsigned char)c;
+
+ if(uc >= '0' && uc <= '9') return uc - (unsigned char)'0';
+ if(uc >= 'a' && uc <= 'f') return uc + 10 - (unsigned char)'a';
+ if(uc >= 'A' && uc <= 'F') return uc + 10 - (unsigned char)'A';
+
+ return 16; /*error*/
+}
+
+void nxagentPropagateArtsdProperties(ScreenPtr pScreen, char *port)
+{
+ Window rootWin;
+ XlibAtom atomReturnType;
+ XlibAtom propAtom;
+ int iReturnFormat;
+ unsigned long ulReturnItems;
+ unsigned long ulReturnBytesLeft;
+ unsigned char *pszReturnData = NULL;
+ int iReturn;
+
+ int i,in;
+ char tchar[] = " ";
+/*
+FIXME: The port information is not used at the moment and produces a
+ warning on recent gcc versions. Do we need such information
+ to run the audio forawrding?
+
+ char *chport;
+ char hex[] = "0123456789abcdef";
+*/
+ rootWin = DefaultRootWindow(nxagentDisplay);
+ propAtom = nxagentAtoms[4]; /* MCOPGLOBALS */
+
+ /*
+ * Get at most 64KB of data.
+ */
+
+ iReturn = XGetWindowProperty(nxagentDisplay,
+ rootWin,
+ propAtom,
+ 0,
+ 65536 / 4,
+ False,
+ XA_STRING,
+ &atomReturnType,
+ &iReturnFormat,
+ &ulReturnItems,
+ &ulReturnBytesLeft,
+ &pszReturnData);
+
+ if (iReturn == Success && atomReturnType != None &&
+ ulReturnItems > 0 && pszReturnData != NULL)
+ {
+ char *local_buf;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPropagateArtsdProperties: Got [%ld] elements of format [%d] with [%ld] bytes left.\n",
+ ulReturnItems, iReturnFormat, ulReturnBytesLeft);
+ #endif
+
+ #ifdef WARNING
+
+ if (ulReturnBytesLeft > 0)
+ {
+ fprintf(stderr, "nxagentPropagateArtsdProperties: WARNING! Could not get the whole ARTSD property data.\n");
+ }
+
+ #endif
+
+ local_buf = (char *) xalloc(strlen((char*)pszReturnData) + 100);
+
+ if (local_buf)
+ {
+ memset(local_buf, 0, strlen((char *) pszReturnData));
+
+ for (i = 0, in = 0; pszReturnData[i] != '\0'; i++)
+ {
+ local_buf[in]=pszReturnData[i];
+
+ if(pszReturnData[i]==':')
+ {
+ i++;
+
+ while(pszReturnData[i]!='\n')
+ {
+ unsigned char h;
+ unsigned char l;
+
+ h = fromHexNibble(pszReturnData[i]);
+ i++;
+ if(pszReturnData[i]=='\0') continue;
+ l = fromHexNibble(pszReturnData[i]);
+ i++;
+
+ if(h >= 16 || l >= 16) continue;
+
+ /*
+ * FIXME: The array tchar[] was used uninitialized.
+ * It's not clear to me the original purpose of the
+ * piece of code using it. To be removed in future
+ * versions.
+ */
+
+ tchar[0]=tchar[1];
+ tchar[1]=tchar[2];
+ tchar[2]=tchar[3];
+ tchar[3] = (h << 4) + l;
+ tchar[4]='\0';
+
+ if (strncmp(tchar, "tcp:", 4) == 0)
+ {
+ local_buf[in-7]='1';
+ local_buf[in-6]=strlen(port)+47;
+
+ in++;
+ local_buf[in]=pszReturnData[i-2];
+ in++;
+ local_buf[in]=pszReturnData[i-1];
+
+ strcat(local_buf,"6c6f63616c686f73743a");
+ in+=20;
+
+/*
+FIXME: The port information is not used at the moment and produces a
+ warning on recent gcc versions. Do we need such information
+ to run the audio forawrding?
+
+ chport=&port[0];
+
+ while(*chport!='\0')
+ {
+ in++;
+ local_buf[in]=hex[(*chport >> 4) & 0xf];
+ in++;
+ local_buf[in]=hex[*chport & 0xf];
+ *chport++;
+ }
+*/
+ strcat(local_buf,"00");
+ in+=2;
+
+ while(pszReturnData[i]!='\n')
+ {
+ i++;
+ }
+ }
+ else
+ {
+ in++;
+ local_buf[in]=pszReturnData[i-2];
+ in++;
+ local_buf[in]=pszReturnData[i-1];
+ }
+ }
+
+ in++;
+ local_buf[in]=pszReturnData[i];
+ }
+
+ in++;
+ }
+
+ local_buf[in]=0;
+
+ if (strlen(local_buf))
+ {
+ mcop_local_atom = MakeAtom(mcop_atom, strlen(mcop_atom), 1);
+
+ ChangeWindowProperty(WindowTable[pScreen->myNum],
+ mcop_local_atom,
+ XA_STRING,
+ iReturnFormat, PropModeReplace,
+ strlen(local_buf), local_buf, 1);
+ }
+
+ xfree(local_buf);
+ }
+ }
+}
+
+#endif
+
+Bool nxagentReconnectScreen(void *p0)
+{
+ CARD16 w, h;
+ PixmapPtr pPixmap = (PixmapPtr)nxagentDefaultScreen->devPrivate;
+ int flexibility;
+ Mask mask;
+
+ flexibility = *(int*)p0;
+
+#if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_SCREEN_DEBUG)
+ fprintf(stderr, "nxagentReconnectScreen\n");
+#endif
+
+ if (!nxagentOpenScreen(0, nxagentDefaultScreen, nxagentArgc, nxagentArgv))
+ {
+ return False;
+ }
+
+ nxagentPixmap(pPixmap) = XCreatePixmap(nxagentDisplay,
+ nxagentDefaultWindows[nxagentDefaultScreen->myNum],
+ pPixmap -> drawable.width,
+ pPixmap -> drawable.height,
+ pPixmap -> drawable.depth);
+#ifdef NXAGENT_RECONNECT_SCREEN_DEBUG
+ fprintf(stderr, "nxagentReconnectScreen: recreated %p - ID %lx\n",
+ pPixmap,
+ nxagentPixmap( pPixmap ));
+#endif
+ w = 16;
+ h = 16;
+ (*nxagentDefaultScreen->QueryBestSize)(StippleShape, &w, &h, nxagentDefaultScreen);
+ if (!(nxagentPixmap(nxagentDefaultScreen->PixmapPerDepth[0]) =
+ XCreatePixmap(nxagentDisplay,
+ nxagentDefaultDrawables[1],
+ w,
+ h,
+ 1)));
+
+ nxagentGetDefaultEventMask(&mask);
+ mask |= NXAGENT_KEYBOARD_EVENT_MASK | NXAGENT_POINTER_EVENT_MASK;
+ nxagentSetDefaultEventMask(mask);
+ XSelectInput(nxagentDisplay, nxagentDefaultWindows[0], mask);
+
+ /*
+ * Turn off the screen-saver and reset the
+ * time to the next auto-disconnection.
+ */
+
+ SaveScreens(SCREEN_SAVER_OFF, ScreenSaverActive);
+
+ lastDeviceEventTime.milliseconds = GetTimeInMillis();
+
+ return True;
+}
+
+RRModePtr nxagentRRCustomMode = NULL;
+
+int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, int mmHeight)
+{
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ RROutputPtr output;
+ RRCrtcPtr crtc;
+ RRModePtr mode;
+ xRRModeInfo modeInfo;
+ char name[100];
+ int r, c, m;
+ int refresh = 60;
+ int doNotify = 1;
+
+ if (WindowTable[screen] == NULL)
+ {
+ return 0;
+ }
+
+ UpdateCurrentTime();
+
+ if (nxagentGrabServerInfo.grabstate == SERVER_GRABBED)
+ {
+ /*
+ * If any client grabbed the server it won't expect that screen
+ * configuration changes until it releases the grab. That could
+ * get an X error because available modes are chanded meanwhile.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeScreenConfig: Cancel with grabbed server.\n");
+ #endif
+
+ return 0;
+ }
+
+ pScreen = WindowTable[screen] -> drawable.pScreen;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeScreenConfig: Changing config to %dx%d.\n", width, height);
+ #endif
+
+ r = nxagentResizeScreen(pScreen, width, height, mmWidth, mmHeight);
+
+ if (r != 0)
+ {
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ if (pScrPriv)
+ {
+ output = RRFirstOutput(pScreen);
+
+ if (output && output -> crtc)
+ {
+ crtc = output -> crtc;
+
+ for (c = 0; c < pScrPriv -> numCrtcs; c++)
+ {
+ RRCrtcSet(pScrPriv -> crtcs[c], NULL, 0, 0, RR_Rotate_0, 0, NULL);
+ }
+
+ memset(&modeInfo, '\0', sizeof(modeInfo));
+ sprintf(name, "%dx%d", width, height);
+
+ modeInfo.width = width;
+ modeInfo.height = height;
+ modeInfo.hTotal = width;
+ modeInfo.vTotal = height;
+ modeInfo.dotClock = ((CARD32) width * (CARD32) height *
+ (CARD32) refresh);
+ modeInfo.nameLength = strlen(name);
+
+ if (nxagentRRCustomMode != NULL)
+ {
+ RROutputDeleteUserMode(output, nxagentRRCustomMode);
+ FreeResource(nxagentRRCustomMode -> mode.id, 0);
+
+ if (crtc != NULL && crtc -> mode == nxagentRRCustomMode)
+ {
+ RRCrtcSet(crtc, NULL, 0, 0, RR_Rotate_0, 0, NULL);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeScreenConfig: "
+ "Going to destroy mode %p with refcnt %d.\n",
+ nxagentRRCustomMode, nxagentRRCustomMode->refcnt);
+ #endif
+
+ RRModeDestroy(nxagentRRCustomMode);
+ }
+
+ nxagentRRCustomMode = RRModeGet(&modeInfo, name);
+
+ RROutputAddUserMode(output, nxagentRRCustomMode);
+
+ RRCrtcSet(crtc, nxagentRRCustomMode, 0, 0, RR_Rotate_0, 1, &output);
+
+ RROutputChanged(output, 1);
+
+ doNotify = 0;
+ }
+
+ pScrPriv -> lastSetTime = currentTime;
+
+ pScrPriv->changed = 1;
+ pScrPriv->configChanged = 1;
+ }
+
+ if (doNotify
+)
+ {
+ RRScreenSizeNotify(pScreen);
+ }
+ }
+
+ return r;
+}
+
+void nxagentSaveAreas(PixmapPtr pPixmap, RegionPtr prgnSave, int xorg, int yorg, WindowPtr pWin)
+{
+ PixmapPtr pVirtualPixmap;
+ nxagentPrivPixmapPtr pPrivPixmap;
+ XlibGC gc;
+ XGCValues values;
+ DrawablePtr pDrawable;
+ int i;
+ int xSrc, ySrc, xDst, yDst, w, h;
+ int nRects;
+ int size;
+ BoxPtr pBox;
+ XRectangle *pRects;
+ BoxRec extents;
+ RegionRec cleanRegion;
+
+ miBSWindowPtr pBackingStore = (miBSWindowPtr) pWin -> backStorage;
+
+ pVirtualPixmap = nxagentVirtualPixmap(pPixmap);
+
+ pPrivPixmap = nxagentPixmapPriv(pPixmap);
+
+ pPrivPixmap -> isBackingPixmap = 1;
+
+ fbCopyWindowProc(&pWin -> drawable, &pVirtualPixmap -> drawable, 0, REGION_RECTS(prgnSave),
+ REGION_NUM_RECTS(prgnSave), xorg, yorg, FALSE, FALSE, 0, 0);
+
+ pDrawable = &pWin -> drawable;
+
+ values.subwindow_mode = IncludeInferiors;
+
+ gc = XCreateGC(nxagentDisplay, nxagentWindow(WindowTable[0]), GCSubwindowMode, &values);
+
+ /*
+ * Initialize to the corrupted region.
+ * Coordinates are relative to the window.
+ */
+
+ REGION_INIT(pWin -> pScreen, &cleanRegion, NullBox, 1);
+
+ REGION_COPY(pWin -> pScreen, &cleanRegion, nxagentCorruptedRegion((DrawablePtr) pWin));
+
+ /*
+ * Subtract the corrupted region from the saved region.
+ */
+
+ REGION_SUBTRACT(pWin -> pScreen, &pBackingStore -> SavedRegion, &pBackingStore -> SavedRegion, &cleanRegion);
+
+ /*
+ * Translate the corrupted region. Coordinates
+ * are relative to the backing store pixmap.
+ */
+
+ REGION_TRANSLATE(pWin -> pScreen, &cleanRegion, -pBackingStore -> x, -pBackingStore -> y);
+
+ /*
+ * Compute the clean region to be saved: subtract
+ * the corrupted region from the region to be saved.
+ */
+
+ REGION_SUBTRACT(pWin -> pScreen, &cleanRegion, prgnSave, &cleanRegion);
+
+ nRects = REGION_NUM_RECTS(&cleanRegion);
+ size = nRects * sizeof(*pRects);
+ pRects = (XRectangle *) xalloc(size);
+ pBox = REGION_RECTS(&cleanRegion);
+
+ for (i = nRects; i-- > 0;)
+ {
+ pRects[i].x = pBox[i].x1;
+ pRects[i].y = pBox[i].y1;
+ pRects[i].width = pBox[i].x2 - pBox[i].x1;
+ pRects[i].height = pBox[i].y2 - pBox[i].y1;
+ }
+
+ XSetClipRectangles(nxagentDisplay, gc, 0, 0, pRects, nRects, Unsorted);
+
+ xfree((char *) pRects);
+
+ extents = *REGION_EXTENTS(pWin -> pScreen, &cleanRegion);
+
+ REGION_UNINIT(pWin -> pScreen, &cleanRegion);
+
+ xDst = extents.x1;
+ yDst = extents.y1;
+
+/*
+ * Left here the wrong solution. The window could be not
+ * configured yet on the real X, whilst the x and y in the
+ * WindowRec are the new coordinates. The right solution
+ * is the other, as it is independent from the window
+ * coordinates.
+ *
+ * xSrc = xDst + xorg - pWin -> drawable.x;
+ * ySrc = yDst + yorg - pWin -> drawable.y;
+ */
+
+ xSrc = xDst + pBackingStore -> x;
+ ySrc = yDst + pBackingStore -> y;
+
+ w = extents.x2 - extents.x1;
+ h = extents.y2 - extents.y1;
+
+ XCopyArea(nxagentDisplay, nxagentWindow(pWin), nxagentPixmap(pPixmap), gc,
+ xSrc, ySrc, w, h, xDst, yDst);
+
+ nxagentAddItemBSPixmapList(nxagentPixmap(pPixmap), pPixmap, pWin,
+ pBackingStore -> x, pBackingStore -> y);
+
+ #ifdef TEST
+ fprintf(stderr,"nxagentSaveAreas: Added pixmap [%p] with id [%d] on window [%p] to BSPixmapList.\n",
+ pPixmap, nxagentPixmap(pPixmap), pWin);
+ #endif
+
+ XFreeGC(nxagentDisplay, gc);
+
+ return;
+}
+
+void nxagentRestoreAreas(PixmapPtr pPixmap, RegionPtr prgnRestore, int xorg,
+ int yorg, WindowPtr pWin)
+{
+ PixmapPtr pVirtualPixmap;
+ RegionPtr clipRegion;
+ XlibGC gc;
+ XGCValues values;
+ DrawablePtr pDrawable;
+ int i;
+ int xSrc, ySrc, xDst, yDst, w, h;
+ int nRects;
+ int size;
+ BoxPtr pBox;
+ XRectangle *pRects;
+ BoxRec extents;
+ miBSWindowPtr pBackingStore;
+
+ /*
+ * Limit the area to restore to the
+ * root window size.
+ */
+
+ REGION_INTERSECT(pWin -> pScreen, prgnRestore, prgnRestore,
+ &WindowTable[pWin -> drawable.pScreen -> myNum] -> winSize);
+
+ pBackingStore = (miBSWindowPtr) pWin -> backStorage;
+
+ pVirtualPixmap = nxagentVirtualPixmap(pPixmap);
+
+ fbCopyWindowProc(&pVirtualPixmap -> drawable, &pWin -> drawable, 0, REGION_RECTS(prgnRestore),
+ REGION_NUM_RECTS(prgnRestore), -xorg, -yorg, FALSE, FALSE, 0, 0);
+
+ pDrawable = &pVirtualPixmap -> drawable;
+
+ values.subwindow_mode = ClipByChildren;
+
+ gc = XCreateGC(nxagentDisplay, nxagentWindow(WindowTable[0]), GCSubwindowMode, &values);
+
+ /*
+ * Translate the reference point to the origin of the window.
+ */
+
+ REGION_TRANSLATE(pWin -> drawable.pScreen, prgnRestore,
+ -pWin -> drawable.x - pWin -> borderWidth,
+ -pWin -> drawable.y - pWin -> borderWidth);
+
+ clipRegion = prgnRestore;
+
+ if (nxagentDrawableStatus((DrawablePtr) pPixmap) == NotSynchronized)
+ {
+ clipRegion = REGION_CREATE(pPixmap -> drawable -> pScreen, NullBox, 1);
+
+ REGION_COPY(pPixmap -> drawable -> pScreen, clipRegion,
+ nxagentCorruptedRegion((DrawablePtr) pPixmap));
+
+ /*
+ * Translate the reference point to the origin of the window.
+ */
+
+ REGION_TRANSLATE(pPixmap -> drawable -> pScreen, clipRegion,
+ pBackingStore -> x, pBackingStore -> y);
+
+ REGION_INTERSECT(pPixmap -> drawable -> pScreen, clipRegion, prgnRestore, clipRegion);
+
+ /*
+ * Subtract the corrupted region from the saved areas.
+ * miBSRestoreAreas will return the exposure region.
+ */
+
+ REGION_SUBTRACT(pPixmap -> drawable -> pScreen, &pBackingStore->SavedRegion,
+ &pBackingStore->SavedRegion, clipRegion);
+
+ /*
+ * Store the corrupted region to send expose later.
+ */
+
+ if (nxagentRemoteExposeRegion != NULL)
+ {
+ REGION_TRANSLATE(pPixmap -> drawable -> pScreen, clipRegion, pWin -> drawable.x, pWin -> drawable.y);
+
+ REGION_UNION(pScreen, nxagentRemoteExposeRegion, nxagentRemoteExposeRegion, clipRegion);
+
+ REGION_TRANSLATE(pPixmap -> drawable -> pScreen, clipRegion, -pWin -> drawable.x, -pWin -> drawable.y);
+ }
+
+ /*
+ * Compute the region to be restored.
+ */
+
+ REGION_SUBTRACT(pPixmap -> drawable -> pScreen, clipRegion, prgnRestore, clipRegion);
+ }
+
+ nRects = REGION_NUM_RECTS(clipRegion);
+ size = nRects * sizeof(*pRects);
+ pRects = (XRectangle *) xalloc(size);
+ pBox = REGION_RECTS(clipRegion);
+
+ for (i = nRects; i-- > 0;)
+ {
+ pRects[i].x = pBox[i].x1;
+ pRects[i].y = pBox[i].y1;
+ pRects[i].width = pBox[i].x2 - pBox[i].x1;
+ pRects[i].height = pBox[i].y2 - pBox[i].y1;
+ }
+
+ XSetClipRectangles(nxagentDisplay, gc, 0, 0, pRects, nRects, Unsorted);
+
+ xfree(pRects);
+
+ extents = *REGION_EXTENTS(pWin -> pScreen, clipRegion);
+
+ xDst = extents.x1;
+ yDst = extents.y1;
+
+ xSrc = xDst - xorg + pWin -> drawable.x;
+ ySrc = yDst - yorg + pWin -> drawable.y;
+
+ w = extents.x2 - extents.x1;
+ h = extents.y2 - extents.y1;
+
+ nxagentFlushConfigureWindow();
+
+ XCopyArea(nxagentDisplay, nxagentPixmap(pPixmap), nxagentWindow(pWin), gc,
+ xSrc, ySrc, w, h, xDst, yDst);
+
+ XFreeGC(nxagentDisplay, gc);
+
+ if (clipRegion != NULL && clipRegion != prgnRestore)
+ {
+ REGION_DESTROY(pPixmap -> drawable -> pScreen, clipRegion);
+ }
+
+ /*
+ * Restore the reference point to the origin of the screen.
+ */
+
+ REGION_TRANSLATE(pWin -> drawable.pScreen, prgnRestore,
+ pWin -> drawable.x - pWin -> borderWidth,
+ pWin -> drawable.y + pWin -> borderWidth);
+
+ return;
+}
+
+void nxagentSetWMNormalHints(int screen)
+{
+ XSizeHints sizeHints;
+
+ /*
+ * Change agent window size and size hints.
+ */
+
+ sizeHints.flags = PPosition | PMinSize | PMaxSize;
+ sizeHints.x = nxagentOption(X);
+ sizeHints.y = nxagentOption(Y);
+
+ sizeHints.min_width = MIN_NXAGENT_WIDTH;
+ sizeHints.min_height = MIN_NXAGENT_HEIGHT;
+
+ sizeHints.width = nxagentOption(Width);
+ sizeHints.height = nxagentOption(Height);
+
+ if (nxagentOption(DesktopResize) == 1)
+ {
+ sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ }
+ else
+ {
+ sizeHints.max_width = nxagentOption(RootWidth);
+ sizeHints.max_height = nxagentOption(RootHeight);
+ }
+
+ if (nxagentUserGeometry.flag & XValue || nxagentUserGeometry.flag & YValue)
+ {
+ sizeHints.flags |= USPosition;
+ }
+
+ if (nxagentUserGeometry.flag & WidthValue || nxagentUserGeometry.flag & HeightValue)
+ {
+ sizeHints.flags |= USSize;
+ }
+
+ XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[screen], &sizeHints);
+}
+
+void nxagentShadowAdaptToRatio(void)
+{
+ XSizeHints sizeHints;
+ ScreenPtr pScreen;
+ RegionRec region;
+ BoxRec box;
+
+ pScreen = screenInfo.screens[0];
+
+ nxagentShadowSetRatio(nxagentOption(Width) * 1.0 / nxagentShadowWidth,
+ nxagentOption(Height) * 1.0 / nxagentShadowHeight);
+
+ nxagentShadowCreateMainWindow(pScreen, WindowTable[0], nxagentShadowWidth, nxagentShadowHeight);
+
+ sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+
+ sizeHints.flags = PMaxSize;
+
+ XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &sizeHints);
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = nxagentShadowPixmapPtr -> drawable.width;
+ box.y2 = nxagentShadowPixmapPtr -> drawable.height;
+
+ REGION_INIT(pScreen, &region, &box, 1);
+
+ nxagentMarkCorruptedRegion((DrawablePtr)nxagentShadowPixmapPtr, &region);
+
+ REGION_UNINIT(pScreen, &region);
+}
+
+void nxagentPrintGeometry()
+{
+ int i;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ if (nxagentPrintGeometryFlags && (1 << i))
+ {
+ fprintf(stderr, "Info: Screen [%d] resized to geometry [%dx%d] "
+ "fullscreen [%d].\n", i, screenInfo.screens[i] -> width,
+ screenInfo.screens[i] -> height,
+ nxagentOption(Fullscreen));
+ }
+ }
+
+ nxagentPrintGeometryFlags = 0;
+}
+
+#ifdef DUMP
+
+void nxagentShowPixmap(PixmapPtr pPixmap, int x, int y, int width, int height)
+{
+ static int init = 1;
+ static Display *shadow;
+ static Window win;
+
+ XlibGC gc;
+ XGCValues value;
+ XImage *image;
+ WindowPtr pWin = WindowTable[0];
+ unsigned int format;
+ int depth, pixmapWidth, pixmapHeight, length;
+ char *data;
+
+ depth = pPixmap -> drawable.depth;
+ pixmapWidth = pPixmap -> drawable.width;
+ pixmapHeight = pPixmap -> drawable.height;
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ if (init)
+ {
+ shadow = XOpenDisplay("localhost:0");
+
+ if (shadow == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentShowPixmap: WARNING! Shadow display not opened.\n");
+ #endif
+
+ return;
+ }
+
+ init = False;
+ }
+
+ if (win == 0)
+ {
+ win = XCreateSimpleWindow(shadow, DefaultRootWindow(shadow), 0, 0,
+ width, height, 0, 0xFFCC33, 0xFF);
+
+ XSelectInput(shadow, win, StructureNotifyMask);
+
+ XMapWindow(shadow, win);
+
+ for(;;)
+ {
+ XEvent e;
+
+ XNextEvent(shadow, &e);
+
+ if (e.type == MapNotify)
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ XResizeWindow(nxagentDisplay, win, width, height);
+ XRaiseWindow(nxagentDisplay, win);
+ }
+
+ length = nxagentImageLength(width, height, format, 0, depth);
+
+ if ((data = xalloc(length)) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentShowPixmap: xalloc failed.\n");
+ #endif
+
+ return;
+ }
+
+/*
+FIXME
+ image = XGetImage(nxagentDisplay, nxagentPixmap(pPixmap), x, y,
+ width, height, AllPlanes, format);
+*/
+
+ image = XGetImage(nxagentDisplay, RootWindow(nxagentDisplay, 0), 0, 0,
+ width, height, AllPlanes, format);
+
+ if (image == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentShowPixmap: XGetImage failed.\n");
+ #endif
+
+ if (data)
+ {
+ xfree(data);
+ }
+
+ return;
+ }
+
+ fbGetImage((DrawablePtr)pPixmap, 0, 0,
+ width, height, format, AllPlanes, data);
+
+ memcpy(image -> data, data, length);
+
+ value.foreground = 0xffffff;
+ value.background = 0x000000;
+ value.plane_mask = 0xffffff;
+ value.fill_style = FillSolid;
+
+ gc = XCreateGC(shadow, win, GCBackground |
+ GCForeground | GCFillStyle | GCPlaneMask, &value);
+
+ XSync(shadow, 0);
+
+ NXCleanImage(image);
+
+ XPutImage(shadow, win, gc, image, 0, 0, 0, 0, width, height);
+
+ XFlush(shadow);
+
+ XFreeGC(shadow, gc);
+
+ if (image != NULL)
+ {
+ XDestroyImage(image);
+ }
+
+ if (data != NULL)
+ {
+ xfree(data);
+ }
+
+/*
+FIXME
+ if (win != NULL)
+ {
+ XDestroyWindow(shadow, win);
+ }
+*/
+}
+
+void nxagentFbRestoreArea(PixmapPtr pPixmap, WindowPtr pWin, int xSrc, int ySrc, int width,
+ int height, int xDst, int yDst)
+{
+ Display *shadow;
+
+ XlibGC gc;
+ XGCValues value;
+ XImage *image;
+ unsigned int format;
+ int depth, pixmapWidth, pixmapHeight, length;
+ char *data = NULL;
+ Visual *pVisual;
+
+ depth = pPixmap -> drawable.depth;
+ pixmapWidth = pPixmap -> drawable.width;
+ pixmapHeight = pPixmap -> drawable.height;
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ shadow = nxagentDisplay;
+
+ length = nxagentImageLength(width, height, format, 0, depth);
+
+ if ((data = xalloc(length)) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbRestoreArea: xalloc failed.\n");
+ #endif
+
+ return;
+ }
+/*
+ image = XGetImage(nxagentDisplay, nxagentPixmap(pPixmap), xSrc, ySrc,
+ width, height, AllPlanes, format);
+*/
+
+ if (image == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbRestoreArea: XGetImage failed.\n");
+ #endif
+
+ if (data)
+ {
+ xfree(data);
+ }
+
+ return;
+ }
+
+ fbGetImage((DrawablePtr)pPixmap, xSrc, ySrc,
+ width, height, format, AllPlanes, data);
+
+/*
+FIXME
+*/
+ pVisual = nxagentImageVisual((DrawablePtr) pPixmap, depth);
+
+ if (pVisual == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbRestoreArea: WARNING! Visual not found. Using default visual.\n");
+ #endif
+
+ pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual;
+ }
+
+ image = XCreateImage(nxagentDisplay, pVisual,
+ depth, format, 0, (char *) data,
+ width, height, BitmapPad(nxagentDisplay),
+ nxagentImagePad(width, format, 0, depth));
+/*
+FIXME
+ memcpy(image -> data, data, length);
+*/
+
+ fprintf(stderr, "nxagentFbRestoreArea: Cleaning %d bytes of image.\n", length);
+
+ value.foreground = 0xffffff;
+ value.background = 0x000000;
+ value.plane_mask = 0xffffff;
+ value.fill_style = FillSolid;
+ value.function = GXcopy;
+
+ gc = XCreateGC(shadow, nxagentWindow(WindowTable[0]), GCBackground |
+ GCForeground | GCFillStyle | GCPlaneMask | GCFunction, &value);
+
+ NXCleanImage(image);
+
+ XPutImage(shadow, nxagentWindow(pWin), gc, image, 0, 0, xDst, yDst, width, height);
+
+/*
+FIXME
+*/
+ XFlush(shadow);
+
+ XFreeGC(shadow, gc);
+
+ if (image)
+ {
+ XDestroyImage(image);
+ }
+
+/*
+FIXME
+ if (data)
+ {
+ xfree(data);
+ }
+*/
+}
+
+#endif