3917 lines
106 KiB
C
3917 lines
106 KiB
C
/**************************************************************************/
|
|
/* */
|
|
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
|
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
|
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
|
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
|
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
|
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
|
/* */
|
|
/* NXAGENT, NX protocol compression and NX extensions to this software */
|
|
/* are copyright of the aforementioned persons and companies. */
|
|
/* */
|
|
/* Redistribution and use of the present software is allowed according */
|
|
/* to terms specified in the file LICENSE which comes in the source */
|
|
/* distribution. */
|
|
/* */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* NOTE: This software has received contributions from various other */
|
|
/* contributors, only the core maintainers and supporters are listed as */
|
|
/* copyright holders. Please contact us, if you feel you should be listed */
|
|
/* as copyright holder, as well. */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "X.h"
|
|
#include "Xproto.h"
|
|
#include "gcstruct.h"
|
|
#include "../../include/window.h"
|
|
#include "windowstr.h"
|
|
#include "pixmapstr.h"
|
|
#include "colormapst.h"
|
|
#include "scrnintstr.h"
|
|
#include "region.h"
|
|
#include "dixstruct.h"
|
|
#include "selection.h"
|
|
#include "mi.h"
|
|
#include "fb.h"
|
|
#include "mibstorest.h"
|
|
|
|
#include "Agent.h"
|
|
#include "Display.h"
|
|
#include "Screen.h"
|
|
#include "GCs.h"
|
|
#include "GCOps.h"
|
|
#include "Drawable.h"
|
|
#include "Colormap.h"
|
|
#include "Cursor.h"
|
|
#include "Visual.h"
|
|
#include "Events.h"
|
|
#include "Clipboard.h"
|
|
#include "Args.h"
|
|
#include "Trap.h"
|
|
#include "Rootless.h"
|
|
#include "Atoms.h"
|
|
#include "Client.h"
|
|
#include "Reconnect.h"
|
|
#include "Dialog.h"
|
|
#include "Splash.h"
|
|
#include "Init.h"
|
|
#include "Composite.h"
|
|
#include "Events.h"
|
|
#include "Utils.h"
|
|
|
|
#include <nx/NX.h>
|
|
#include "compext/Compext.h"
|
|
|
|
#include "Xatom.h"
|
|
|
|
/*
|
|
* Used to register the window's privates.
|
|
*/
|
|
|
|
int nxagentWindowPrivateIndex;
|
|
|
|
/*
|
|
* Used to track nxagent window's visibility.
|
|
*/
|
|
|
|
int nxagentVisibility = VisibilityUnobscured;
|
|
|
|
ConfiguredWindowStruct *nxagentConfiguredWindowList;
|
|
StaticResizedWindowStruct *nxagentStaticResizedWindowList;
|
|
|
|
/*
|
|
* Set here the required log level.
|
|
*/
|
|
|
|
#define PANIC
|
|
#define WARNING
|
|
#undef TEST
|
|
#undef DEBUG
|
|
|
|
/*
|
|
* Useful to test the window configuration failures.
|
|
*/
|
|
|
|
#ifdef TEST
|
|
#define MAKE_SYNC_CONFIGURE_WINDOW XSync(nxagentDisplay, 0)
|
|
#else
|
|
#define MAKE_SYNC_CONFIGURE_WINDOW
|
|
#endif
|
|
|
|
extern WindowPtr nxagentViewportFrameLeft;
|
|
extern WindowPtr nxagentViewportFrameRight;
|
|
extern WindowPtr nxagentViewportFrameAbove;
|
|
extern WindowPtr nxagentViewportFrameBelow;
|
|
|
|
extern Bool nxagentReportPrivateWindowIds;
|
|
|
|
#define RECTLIMIT 25
|
|
#define BSPIXMAPLIMIT 128
|
|
|
|
Bool nxagentExposeArrayIsInitialized = False;
|
|
Window nxagentConfiguredSynchroWindow;
|
|
static int nxagentExposeSerial = 0;
|
|
|
|
StoringPixmapPtr nxagentBSPixmapList[BSPIXMAPLIMIT];
|
|
|
|
/*
|
|
* Used to walk through the window hierarchy to find a window
|
|
*/
|
|
|
|
typedef struct _WindowMatch
|
|
{
|
|
WindowPtr pWin;
|
|
Window id;
|
|
} WindowMatchRec;
|
|
|
|
Bool nxagentReconnectAllWindows(void *);
|
|
Bool nxagentDisconnectAllWindows(void);
|
|
Bool nxagentIsIconic(WindowPtr);
|
|
|
|
/*
|
|
* From NXproperty.c.
|
|
*/
|
|
|
|
int GetWindowProperty(WindowPtr, Atom, long, long, Bool, Atom, Atom*, int*,
|
|
unsigned long*, unsigned long*, unsigned char**);
|
|
|
|
/*
|
|
* Other local functions.
|
|
*/
|
|
|
|
static Bool nxagentSomeWindowsAreMapped(void);
|
|
static void nxagentFrameBufferPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what);
|
|
static void nxagentTraverseWindow(WindowPtr, void(*)(void *, XID, void *), void *);
|
|
static void nxagentDisconnectWindow(void *, XID, void *);
|
|
static Bool nxagentLoopOverWindows(void(*)(void *, XID, void *));
|
|
static void nxagentReconfigureWindowCursor(void *, XID, void *);
|
|
static void nxagentReconnectWindow(void *, XID, void *);
|
|
static void nxagentReconfigureWindow(void *, XID, void *);
|
|
static int nxagentForceExposure(WindowPtr pWin, void * ptr);
|
|
|
|
/* by dimbor */
|
|
typedef struct
|
|
{
|
|
CARD32 state;
|
|
Window icon;
|
|
}
|
|
nxagentWMStateRec;
|
|
|
|
/*
|
|
* This is currently unused.
|
|
*/
|
|
|
|
#ifdef TEST
|
|
static Bool nxagentCheckWindowIntegrity(WindowPtr pWin);
|
|
#endif
|
|
|
|
WindowPtr nxagentGetWindowFromID(Window id)
|
|
{
|
|
WindowPtr pWin = screenInfo.screens[0]->root;
|
|
|
|
while (pWin && nxagentWindowPriv(pWin))
|
|
{
|
|
if (nxagentWindow(pWin) == id)
|
|
{
|
|
return pWin;
|
|
}
|
|
|
|
if (pWin -> nextSib)
|
|
{
|
|
pWin = pWin -> nextSib;
|
|
}
|
|
else
|
|
{
|
|
pWin = pWin -> firstChild;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int nxagentFindWindowMatch(WindowPtr pWin, void * ptr)
|
|
{
|
|
WindowMatchRec *match = (WindowMatchRec *) ptr;
|
|
|
|
if (match -> id == nxagentWindow(pWin))
|
|
{
|
|
match -> pWin = pWin;
|
|
return WT_STOPWALKING;
|
|
}
|
|
else
|
|
{
|
|
return WT_WALKCHILDREN;
|
|
}
|
|
}
|
|
|
|
WindowPtr nxagentWindowPtr(Window window)
|
|
{
|
|
WindowMatchRec match = {.pWin = NullWindow, .id = window};
|
|
|
|
for (int i = 0; i < nxagentNumScreens; i++)
|
|
{
|
|
WalkTree(screenInfo.screens[i], nxagentFindWindowMatch, (void *) &match);
|
|
|
|
if (match.pWin)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return match.pWin;
|
|
}
|
|
|
|
/*
|
|
* from "Definition of the Porting Layer for X v11 Sample Server":
|
|
*
|
|
* This routine is a hook for when DIX creates a window. It should
|
|
* fill in the "Window Procedures in the WindowRec" below and also
|
|
* allocate the devPrivate block for it.
|
|
*
|
|
* See Xserver/fb/fbwindow.c for the sample server implementation.
|
|
*/
|
|
Bool nxagentCreateWindow(WindowPtr pWin)
|
|
{
|
|
unsigned long mask;
|
|
XSetWindowAttributes attributes;
|
|
Visual *visual;
|
|
ColormapPtr pCmap;
|
|
|
|
if (nxagentScreenTrap)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
if (pWin->drawable.class == InputOnly)
|
|
{
|
|
mask = CWEventMask;
|
|
visual = CopyFromParent;
|
|
}
|
|
else
|
|
{
|
|
mask = CWEventMask | CWBackingStore;
|
|
|
|
if (pWin->optional)
|
|
{
|
|
mask |= CWBackingPlanes | CWBackingPixel;
|
|
attributes.backing_planes = pWin->optional->backingBitPlanes;
|
|
attributes.backing_pixel = pWin->optional->backingPixel;
|
|
}
|
|
|
|
attributes.backing_store = NotUseful;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCreateWindow: Backing store on window at [%p] is [%d].\n",
|
|
(void*)pWin, attributes.backing_store);
|
|
#endif
|
|
|
|
/*
|
|
FIXME: We need to set save under on the real display?
|
|
*/
|
|
if (nxagentSaveUnder)
|
|
{
|
|
mask |= CWSaveUnder;
|
|
attributes.save_under = False;
|
|
}
|
|
|
|
if (pWin->parent)
|
|
{
|
|
if (pWin->optional && pWin->optional->visual != wVisual(pWin->parent))
|
|
{
|
|
visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
|
|
mask |= CWColormap;
|
|
if (pWin->optional->colormap)
|
|
{
|
|
pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP);
|
|
attributes.colormap = nxagentColormap(pCmap);
|
|
}
|
|
else
|
|
{
|
|
attributes.colormap = nxagentDefaultVisualColormap(visual);
|
|
}
|
|
}
|
|
else if (pWin->optional)
|
|
{
|
|
visual = CopyFromParent;
|
|
}
|
|
else
|
|
{
|
|
visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
|
|
mask |= CWColormap;
|
|
attributes.colormap = nxagentDefaultVisualColormap(visual);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* root windows have their own colormaps at creation time */
|
|
visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
|
|
pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP);
|
|
mask |= CWColormap;
|
|
attributes.colormap = nxagentColormap(pCmap);
|
|
}
|
|
}
|
|
|
|
if (mask & CWEventMask)
|
|
{
|
|
attributes.event_mask = nxagentGetEventMask(pWin);
|
|
}
|
|
#ifdef WARNING
|
|
else
|
|
{
|
|
attributes.event_mask = NoEventMask;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Select the event mask if window is a top level window. This at
|
|
* least makes the keyboard barely work.
|
|
*/
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCreateWindow: Going to create new window.\n");
|
|
#endif
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCreateWindow: Creating %swindow at %p current event mask = %lX mask & CWEventMask = %ld "
|
|
"event_mask = %lX\n",
|
|
nxagentWindowTopLevel(pWin) ? "toplevel " : "", (void*)pWin, pWin -> eventMask,
|
|
mask & CWEventMask, attributes.event_mask);
|
|
|
|
fprintf(stderr, "nxagentCreateWindow: position [%d,%d] size [%d,%d] depth [%d] border [%d] class [%d].\n",
|
|
pWin->origin.x - wBorderWidth(pWin), pWin->origin.y - wBorderWidth(pWin),
|
|
pWin->drawable.width, pWin->drawable.height, pWin->drawable.depth, pWin->borderWidth,
|
|
pWin->drawable.class);
|
|
#endif
|
|
|
|
nxagentWindowPriv(pWin)->window = XCreateWindow(nxagentDisplay,
|
|
nxagentWindowParent(pWin),
|
|
pWin->origin.x -
|
|
wBorderWidth(pWin),
|
|
pWin->origin.y -
|
|
wBorderWidth(pWin),
|
|
pWin->drawable.width,
|
|
pWin->drawable.height,
|
|
pWin->borderWidth,
|
|
pWin->drawable.depth,
|
|
pWin->drawable.class,
|
|
visual,
|
|
mask, &attributes);
|
|
|
|
nxagentWindowPriv(pWin) -> isMapped = 0;
|
|
nxagentWindowPriv(pWin) -> isRedirected = 0;
|
|
nxagentWindowPriv(pWin) -> visibilityState = VisibilityUnobscured;
|
|
nxagentWindowPriv(pWin) -> corruptedRegion = RegionCreate(NULL, 1);
|
|
nxagentWindowPriv(pWin) -> hasTransparentChildren = 0;
|
|
nxagentWindowPriv(pWin) -> containGlyphs = 0;
|
|
nxagentWindowPriv(pWin) -> corruptedId = 0;
|
|
nxagentWindowPriv(pWin) -> deferredBackgroundExpose = 0;
|
|
nxagentWindowPriv(pWin) -> synchronizationBitmap = NullPixmap;
|
|
nxagentWindowPriv(pWin) -> corruptedTimestamp = 0;
|
|
nxagentWindowPriv(pWin) -> splitResource = NULL;
|
|
|
|
if (nxagentOption(Rootless))
|
|
{
|
|
nxagentWindowPriv(pWin) -> isMapped = 0;
|
|
|
|
if (pWin != nxagentRootlessWindow)
|
|
{
|
|
WindowPtr pParent = pWin -> parent;
|
|
|
|
if (pParent && nxagentWindowPriv(pParent) -> isMapped == 1)
|
|
{
|
|
nxagentWindowPriv(pWin) -> isMapped = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nxagentReportPrivateWindowIds)
|
|
{
|
|
fprintf(stderr, "NXAGENT_WINDOW_ID: %s_WINDOW,WID:[0x%x],INT:[0x%x]\n",
|
|
(pWin->drawable.id == pWin->drawable.pScreen->root->drawable.id) ? "ROOT" : "PRIVATE",
|
|
nxagentWindowPriv(pWin)->window, pWin->drawable.id);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
{
|
|
char *winname = NULL;
|
|
|
|
if (-1 != asprintf(&winname, "%s %s[0x%lx]", nxagentWindowName,
|
|
(pWin->drawable.id == pWin->drawable.pScreen->root->drawable.id) ? "Root" : "Private",
|
|
pWin->drawable.id))
|
|
{
|
|
Xutf8SetWMProperties(nxagentDisplay, nxagentWindowPriv(pWin)->window,
|
|
winname, winname, NULL , 0 , NULL, NULL, NULL);
|
|
SAFE_free(winname);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: Created new window with id [0x%x].\n", __func__,
|
|
nxagentWindowPriv(pWin)->window);
|
|
#endif
|
|
|
|
/*
|
|
* Set the WM_DELETE_WINDOW protocols on every top level
|
|
* window. Also redirect the window if it is a top level.
|
|
*/
|
|
|
|
if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin))
|
|
{
|
|
XlibAtom prop = nxagentMakeAtom("WM_PROTOCOLS", strlen("WM_PROTOCOLS"), True);
|
|
XlibAtom atom = nxagentMakeAtom("WM_DELETE_WINDOW", strlen("WM_DELETE_WINDOW"), True);
|
|
|
|
XSetWMProtocols(nxagentDisplay, nxagentWindowPriv(pWin)->window, &atom, 1);
|
|
|
|
nxagentAddPropertyToList(prop, pWin);
|
|
|
|
/*
|
|
* Redirect the window to the off-screen memory, if the composite
|
|
* extension is supported on the display.
|
|
*/
|
|
/*
|
|
FIXME: Do all the windows for which nxagentWindowTopLevel(pWin)
|
|
returns true need to be redirected?
|
|
*/
|
|
nxagentRedirectWindow(pWin);
|
|
}
|
|
|
|
if ((nxagentRealWindowProp) && (!nxagentWindowTopLevel(pWin)))
|
|
{
|
|
Atom prop = MakeAtom("NX_REAL_WINDOW", strlen("NX_REAL_WINDOW"), True);
|
|
|
|
if (ChangeWindowProperty(pWin, prop, XA_WINDOW, 32, PropModeReplace, 1, nxagentWindowPriv(pWin), 1) != Success)
|
|
{
|
|
fprintf(stderr, "nxagentCreateWindow: Adding NX_REAL_WINDOW failed.\n");
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
fprintf(stderr, "nxagentCreateWindow: Added NX_REAL_WINDOW for Window ID [%x].\n", nxagentWindowPriv(pWin)->window);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
nxagentWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
|
|
nxagentWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
|
|
nxagentWindowPriv(pWin)->width = pWin->drawable.width;
|
|
nxagentWindowPriv(pWin)->height = pWin->drawable.height;
|
|
nxagentWindowPriv(pWin)->borderWidth = pWin->borderWidth;
|
|
nxagentWindowPriv(pWin)->siblingAbove = None;
|
|
nxagentWindowPriv(pWin)->pPicture = NULL;
|
|
|
|
if (pWin->nextSib)
|
|
{
|
|
nxagentWindowPriv(pWin->nextSib)->siblingAbove = nxagentWindow(pWin);
|
|
}
|
|
|
|
#ifdef SHAPE
|
|
nxagentWindowPriv(pWin)->boundingShape = NULL;
|
|
nxagentWindowPriv(pWin)->clipShape = NULL;
|
|
#endif /* SHAPE */
|
|
|
|
fbCreateWindow(pWin);
|
|
|
|
/*
|
|
* Only the root window will have the right colormap.
|
|
*/
|
|
|
|
if (!pWin->parent)
|
|
{
|
|
nxagentSetInstalledColormapWindows(pWin->drawable.pScreen);
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
/* set the NX_AGENT_VERSION property for the given window (normally
|
|
the root window) */
|
|
void nxagentSetVersionProperty(WindowPtr pWin)
|
|
{
|
|
char *name = "NX_AGENT_VERSION";
|
|
Atom prop = MakeAtom(name, strlen(name), True);
|
|
|
|
if (ChangeWindowProperty(pWin, prop, XA_STRING, 8, PropModeReplace, strlen(NX_VERSION_CURRENT_STRING), NX_VERSION_CURRENT_STRING, True) != Success)
|
|
{
|
|
fprintf(stderr, "%s: Adding property [%s], value [%s] failed.\n", __func__, name, NX_VERSION_CURRENT_STRING);
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
fprintf(stderr, "%s: Added property [%s], value [%s] for root window [%x].\n", __func__, name, NX_VERSION_CURRENT_STRING, pWin);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
Bool nxagentSomeWindowsAreMapped(void)
|
|
{
|
|
WindowPtr pWin = screenInfo.screens[0]->root -> firstChild;
|
|
|
|
while (pWin)
|
|
{
|
|
if ((pWin -> mapped || nxagentIsIconic(pWin)) &&
|
|
pWin -> drawable.class == InputOutput)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
pWin = pWin -> nextSib;
|
|
}
|
|
|
|
return False;
|
|
}
|
|
|
|
/*
|
|
* from "Definition of the Porting Layer for X v11 Sample Server":
|
|
*
|
|
* This routine is a hook for when DIX destroys a window. It should
|
|
* deallocate the devPrivate block for it and any other blocks that
|
|
* need to be freed, besides doing other cleanup actions.
|
|
*
|
|
* See Xserver/fb/fbwindow.c for the sample server implementation.
|
|
*/
|
|
Bool nxagentDestroyWindow(WindowPtr pWin)
|
|
{
|
|
nxagentPrivWindowPtr pWindowPriv;
|
|
|
|
if (nxagentScreenTrap)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
nxagentClearClipboard(NULL, pWin);
|
|
|
|
for (int j = 0; j < nxagentExposeQueue.length; j++)
|
|
{
|
|
int i = (nxagentExposeQueue.start + j) % EXPOSED_SIZE;
|
|
|
|
if (nxagentExposeQueue.exposures[i].pWindow == pWin)
|
|
{
|
|
if (nxagentExposeQueue.exposures[i].localRegion != NullRegion)
|
|
{
|
|
RegionDestroy(nxagentExposeQueue.exposures[i].localRegion);
|
|
}
|
|
|
|
nxagentExposeQueue.exposures[i].localRegion = NullRegion;
|
|
|
|
if (nxagentExposeQueue.exposures[i].remoteRegion != NullRegion)
|
|
{
|
|
RegionDestroy(nxagentExposeQueue.exposures[i].remoteRegion);
|
|
}
|
|
|
|
nxagentExposeQueue.exposures[i].remoteRegion = NullRegion;
|
|
}
|
|
}
|
|
|
|
nxagentDeleteConfiguredWindow(pWin);
|
|
|
|
pWindowPriv = nxagentWindowPriv(pWin);
|
|
|
|
if (pWin->nextSib)
|
|
{
|
|
nxagentWindowPriv(pWin->nextSib)->siblingAbove =
|
|
pWindowPriv->siblingAbove;
|
|
}
|
|
|
|
#ifdef SHAPE
|
|
if (pWindowPriv->boundingShape)
|
|
{
|
|
RegionDestroy(pWindowPriv->boundingShape);
|
|
}
|
|
|
|
if (pWindowPriv->clipShape)
|
|
{
|
|
RegionDestroy(pWindowPriv->clipShape);
|
|
}
|
|
#endif
|
|
|
|
if (pWindowPriv -> corruptedRegion)
|
|
{
|
|
RegionDestroy(pWindowPriv -> corruptedRegion);
|
|
pWindowPriv -> corruptedRegion = NULL;
|
|
}
|
|
|
|
if (nxagentSynchronization.pDrawable == (DrawablePtr) pWin)
|
|
{
|
|
nxagentSynchronization.pDrawable = NULL;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentDestroyWindow: Synchronization drawable [%p] removed from resources.\n",
|
|
(void *) pWin);
|
|
#endif
|
|
}
|
|
|
|
nxagentDestroyCorruptedResource((DrawablePtr) pWin, RT_NX_CORR_WINDOW);
|
|
nxagentDestroyDrawableBitmap((DrawablePtr) pWin);
|
|
|
|
if (pWindowPriv -> splitResource != NULL)
|
|
{
|
|
nxagentReleaseSplit((DrawablePtr) pWin);
|
|
}
|
|
|
|
XDestroyWindow(nxagentDisplay, nxagentWindow(pWin));
|
|
|
|
if (nxagentOption(Rootless))
|
|
{
|
|
nxagentRootlessDelTopLevelWindow(pWin);
|
|
}
|
|
|
|
pWindowPriv->window = None;
|
|
|
|
if (pWin -> optional)
|
|
{
|
|
pWin -> optional -> userProps = NULL;
|
|
}
|
|
|
|
if (nxagentOption(Rootless) && nxagentRootlessDialogPid == 0 &&
|
|
!nxagentLastWindowDestroyed && nxagentSomeWindowsAreMapped() == False)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentDestroyWindow: Last mapped window as been destroyed.\n");
|
|
#endif
|
|
|
|
nxagentLastWindowDestroyed = True;
|
|
nxagentLastWindowDestroyedTime = GetTimeInMillis();
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
/*
|
|
* from "Definition of the Porting Layer for X v11 Sample Server":
|
|
*
|
|
* This routine is a hook for when DIX moves or resizes a window. It
|
|
* should do whatever private operations need to be done when a window
|
|
* is moved or resized. For instance, if DDX keeps a pixmap tile used
|
|
* for drawing the background or border, and it keeps the tile rotated
|
|
* such that it is longword aligned to longword locations in the frame
|
|
* buffer, then you should rotate your tiles here. The actual graphics
|
|
* involved in moving the pixels on the screen and drawing the border
|
|
* are handled by CopyWindow(), below.
|
|
*
|
|
* See Xserver/fb/fbwindow.c for the sample server implementation.
|
|
*/
|
|
Bool nxagentPositionWindow(WindowPtr pWin, int x, int y)
|
|
{
|
|
if (nxagentScreenTrap)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentPositionWindow: Changing position of window [%p][%ld] to [%d,%d].\n",
|
|
(void *) pWin, nxagentWindow(pWin), x, y);
|
|
#endif
|
|
|
|
nxagentAddConfiguredWindow(pWin, CWSibling | CWX | CWY | CWWidth |
|
|
CWHeight | CWBorderWidth);
|
|
|
|
return True;
|
|
}
|
|
|
|
void nxagentRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib)
|
|
{
|
|
if (nxagentScreenTrap)
|
|
{
|
|
return;
|
|
}
|
|
|
|
nxagentAddConfiguredWindow(pWin, CW_RootlessRestack);
|
|
}
|
|
|
|
void nxagentSwitchFullscreen(ScreenPtr pScreen, Bool switchOn)
|
|
{
|
|
if (nxagentOption(Rootless))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!switchOn)
|
|
{
|
|
nxagentWMDetect();
|
|
|
|
/*
|
|
* The smart scheduler could be stopped while waiting for the
|
|
* reply. In this case we need to yield explicitly to avoid to be
|
|
* stuck in the dispatch loop forever.
|
|
*/
|
|
|
|
isItTimeToYield = 1;
|
|
|
|
if (!nxagentWMIsRunning)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "Warning: Can't switch to window mode, no window manager "
|
|
"has been detected.\n");
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: Switching to %s mode.\n", __func__,
|
|
switchOn ? "fullscreen" : "windowed");
|
|
#endif
|
|
|
|
nxagentChangeOption(Fullscreen, switchOn);
|
|
|
|
XEvent e = {
|
|
.xclient.type = ClientMessage,
|
|
.xclient.message_type = nxagentAtoms[13], /* _NET_WM_STATE */
|
|
.xclient.display = nxagentDisplay,
|
|
.xclient.window = nxagentDefaultWindows[pScreen -> myNum],
|
|
.xclient.format = 32,
|
|
.xclient.data.l[0] = nxagentOption(Fullscreen) ? 1 : 0,
|
|
.xclient.data.l[1] = nxagentAtoms[14] /* _NET_WM_STATE_FULLSCREEN */
|
|
};
|
|
XSendEvent(nxagentDisplay, DefaultRootWindow(nxagentDisplay), False,
|
|
SubstructureRedirectMask, &e);
|
|
|
|
if (switchOn)
|
|
{
|
|
nxagentFullscreenWindow = nxagentDefaultWindows[pScreen -> myNum];
|
|
nxagentGrabPointerAndKeyboard(NULL);
|
|
}
|
|
else
|
|
{
|
|
nxagentFullscreenWindow = None;
|
|
|
|
/* if we had AutoGrab before entering fullscreen reactivate it now */
|
|
if (nxagentOption(AutoGrab))
|
|
nxagentGrabPointerAndKeyboard(NULL);
|
|
else
|
|
nxagentUngrabPointerAndKeyboard(NULL);
|
|
}
|
|
}
|
|
|
|
void nxagentSwitchAllScreens(ScreenPtr pScreen, Bool switchOn)
|
|
{
|
|
if (nxagentOption(Rootless))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!switchOn)
|
|
{
|
|
nxagentWMDetect();
|
|
|
|
if (!nxagentWMIsRunning)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "Warning: Can't switch to window mode, no window manager has been detected.\n");
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
Window w = nxagentDefaultWindows[pScreen -> myNum];
|
|
|
|
/*
|
|
* override_redirect makes the window manager ignore the window and
|
|
* not add decorations, see ICCCM)
|
|
*/
|
|
XSetWindowAttributes attributes = {
|
|
.override_redirect = switchOn
|
|
};
|
|
unsigned long valuemask = CWOverrideRedirect;
|
|
XUnmapWindow(nxagentDisplay, w);
|
|
XChangeWindowAttributes(nxagentDisplay, w, valuemask, &attributes);
|
|
|
|
XReparentWindow(nxagentDisplay, w, DefaultRootWindow(nxagentDisplay), 0, 0);
|
|
|
|
if (switchOn)
|
|
{
|
|
/*
|
|
* Change to fullscreen mode.
|
|
*/
|
|
|
|
int i;
|
|
XEvent e;
|
|
|
|
/*
|
|
* Wait for window manager reparenting the default window.
|
|
*/
|
|
|
|
for (i = 0; i < 100 && nxagentWMIsRunning; i++)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: WARNING! Going to wait for the ReparentNotify event.\n", __func__);
|
|
#endif
|
|
|
|
if (XCheckTypedWindowEvent(nxagentDisplay, w, ReparentNotify, &e))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: found ReparentNotify event in iteration [%d].\n", __func__, i);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* This should also flush the NX link for us.
|
|
*/
|
|
|
|
XSync(nxagentDisplay, 0);
|
|
|
|
nxagentWaitEvents(nxagentDisplay, 50);
|
|
}
|
|
|
|
if (i < 100)
|
|
{
|
|
/*
|
|
* The window manager has done with the reparent operation. We
|
|
* can resize and map the window.
|
|
*/
|
|
|
|
nxagentChangeOption(Fullscreen, True);
|
|
nxagentChangeOption(AllScreens, True);
|
|
|
|
/*
|
|
* Save the window-mode configuration.
|
|
*/
|
|
|
|
nxagentChangeOption(SavedX, nxagentOption(X));
|
|
nxagentChangeOption(SavedY, nxagentOption(Y));
|
|
nxagentChangeOption(SavedWidth, nxagentOption(Width));
|
|
nxagentChangeOption(SavedHeight, nxagentOption(Height));
|
|
nxagentChangeOption(SavedRootWidth, nxagentOption(RootWidth));
|
|
nxagentChangeOption(SavedRootHeight, nxagentOption(RootHeight));
|
|
|
|
/*
|
|
* Reconf the Default window.
|
|
*/
|
|
|
|
nxagentChangeOption(X, 0);
|
|
nxagentChangeOption(Y, 0);
|
|
nxagentChangeOption(Width, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
|
|
nxagentChangeOption(Height, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
|
|
|
|
/*
|
|
* Move the root window.
|
|
*/
|
|
|
|
nxagentChangeOption(RootX, (nxagentOption(Width) - nxagentOption(RootWidth)) / 2);
|
|
nxagentChangeOption(RootY, (nxagentOption(Height) - nxagentOption(RootHeight)) / 2);
|
|
nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth));
|
|
nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight));
|
|
|
|
XMoveResizeWindow(nxagentDisplay, w, nxagentOption(X), nxagentOption(Y),
|
|
nxagentOption(Width), nxagentOption(Height));
|
|
|
|
nxagentUpdateViewportFrame(0, 0, nxagentOption(RootWidth), nxagentOption(RootHeight));
|
|
|
|
XMoveWindow(nxagentDisplay, nxagentWindow(pScreen->root),
|
|
nxagentOption(RootX), nxagentOption(RootY));
|
|
|
|
/*
|
|
* We disable the screensaver on the real Xserver when changing mode to
|
|
* fullscreen. Is it really needed?
|
|
*/
|
|
|
|
XSetScreenSaver(nxagentDisplay, 0, 0, DefaultExposures, DefaultBlanking);
|
|
|
|
if (nxagentIconWindow == None)
|
|
{
|
|
nxagentIconWindow = nxagentCreateIconWindow();
|
|
XMapWindow(nxagentDisplay, nxagentIconWindow);
|
|
}
|
|
|
|
XMapRaised(nxagentDisplay, w);
|
|
XSetInputFocus(nxagentDisplay, w, RevertToParent, CurrentTime);
|
|
XCheckTypedWindowEvent(nxagentDisplay, w, LeaveNotify, &e);
|
|
nxagentFullscreenWindow = w;
|
|
|
|
if (nxagentOption(DesktopResize))
|
|
{
|
|
if (!nxagentOption(Shadow))
|
|
{
|
|
nxagentChangeScreenConfig(0, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)),
|
|
HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)), True);
|
|
}
|
|
else
|
|
{
|
|
nxagentShadowAdaptToRatio();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* We have waited for a reparent event unsuccessfully.
|
|
* Something happened to the window manager.
|
|
*/
|
|
|
|
#ifdef WARNING
|
|
fprintf(stderr, "%s: WARNING! Expected ReparentNotify event missing.\n", __func__);
|
|
#endif
|
|
|
|
nxagentWMIsRunning = False;
|
|
attributes.override_redirect = False;
|
|
XChangeWindowAttributes(nxagentDisplay, w, valuemask, &attributes);
|
|
XMapWindow(nxagentDisplay, w);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* FIXME:
|
|
* It could be necessary:
|
|
* - To restore screensaver.
|
|
* - To set or reset nxagentForceBackingStore flag.
|
|
* - To propagate device settings to the X server if no WM is running.
|
|
*/
|
|
|
|
/*
|
|
* Change to windowed mode.
|
|
*/
|
|
|
|
nxagentChangeOption(Fullscreen, False);
|
|
nxagentChangeOption(AllScreens, False);
|
|
|
|
XDestroyWindow(nxagentDisplay, nxagentIconWindow);
|
|
|
|
nxagentIconWindow = nxagentFullscreenWindow = None;
|
|
|
|
if (nxagentOption(DesktopResize))
|
|
{
|
|
nxagentChangeOption(RootWidth, nxagentOption(SavedRootWidth));
|
|
nxagentChangeOption(RootHeight, nxagentOption(SavedRootHeight));
|
|
|
|
if (!nxagentOption(Shadow))
|
|
{
|
|
nxagentChangeScreenConfig(0, nxagentOption(RootWidth),
|
|
nxagentOption(RootHeight), True);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* FIXME: These are 0 most of the time nowadays. The effect is,
|
|
* that the window is moving a bit to right/bottom every time
|
|
* fullscreen mode is left. To fix this query the frame extents
|
|
* from the window manager via _NET_REQUEST_FRAME_EXTENTS
|
|
*/
|
|
|
|
if (nxagentOption(WMBorderWidth) > 0)
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "%s: WMBorderWidth [%d]\n", __func__, nxagentOption(WMBorderWidth));
|
|
#endif
|
|
nxagentChangeOption(X, nxagentOption(SavedX) - nxagentOption(WMBorderWidth));
|
|
}
|
|
else
|
|
{
|
|
nxagentChangeOption(X, nxagentOption(SavedX));
|
|
}
|
|
|
|
if (nxagentOption(WMTitleHeight) > 0)
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "%s: WMTitleHeight [%d]\n", __func__, nxagentOption(WMTitleHeight));
|
|
#endif
|
|
nxagentChangeOption(Y, nxagentOption(SavedY) - nxagentOption(WMTitleHeight));
|
|
}
|
|
else
|
|
{
|
|
nxagentChangeOption(Y, nxagentOption(SavedY));
|
|
}
|
|
|
|
nxagentChangeOption(Width, nxagentOption(SavedWidth));
|
|
nxagentChangeOption(Height, nxagentOption(SavedHeight));
|
|
|
|
if (nxagentOption(Shadow) && nxagentOption(DesktopResize))
|
|
{
|
|
nxagentShadowAdaptToRatio();
|
|
}
|
|
|
|
XMoveResizeWindow(nxagentDisplay, w, nxagentOption(X), nxagentOption(Y),
|
|
nxagentOption(Width), nxagentOption(Height));
|
|
|
|
nxagentUpdateViewportFrame(0, 0, nxagentOption(Width), nxagentOption(Height));
|
|
|
|
XMoveWindow(nxagentDisplay, nxagentWindow(pScreen->root), 0, 0);
|
|
XMapWindow(nxagentDisplay, w);
|
|
|
|
nxagentChangeOption(RootX, 0);
|
|
nxagentChangeOption(RootY, 0);
|
|
}
|
|
|
|
XMoveResizeWindow(nxagentDisplay, nxagentInputWindows[0], 0, 0,
|
|
nxagentOption(Width), nxagentOption(Height));
|
|
|
|
/* if we had AutoGrab before entering fullscreen reactivate it now */
|
|
if (nxagentOption(AutoGrab))
|
|
nxagentGrabPointerAndKeyboard(NULL);
|
|
|
|
nxagentSetPrintGeometry(pScreen -> myNum);
|
|
}
|
|
|
|
#ifdef VIEWPORT_FRAME
|
|
|
|
void nxagentUpdateViewportFrame(int x, int y, int w, int h)
|
|
{
|
|
/*
|
|
* Four virtual windows make a frame around the viewport. We move the frame
|
|
* with the viewport together. The areas going into the viewport were covered by
|
|
* the frame and become exposed. This make the agent send expose events to his
|
|
* clients.
|
|
*/
|
|
|
|
XID values[3];
|
|
Mask mask;
|
|
|
|
/*
|
|
* nxagentScreenTrap = True;
|
|
*/
|
|
|
|
values[2] = Above;
|
|
|
|
values[1] = nxagentOption(RootHeight);
|
|
|
|
mask = CWX | CWHeight | CWStackMode;
|
|
values[0] = x - NXAGENT_FRAME_WIDTH;
|
|
ConfigureWindow(nxagentViewportFrameLeft, mask, (XID *) &values, serverClient);
|
|
|
|
values[0] = x + w;
|
|
ConfigureWindow(nxagentViewportFrameRight, mask, (XID *) &values, serverClient);
|
|
|
|
values[1] = nxagentOption(RootWidth);
|
|
|
|
mask = CWY | CWWidth | CWStackMode;
|
|
values[0] = y - NXAGENT_FRAME_WIDTH;
|
|
ConfigureWindow(nxagentViewportFrameAbove, mask, (XID *) &values, serverClient);
|
|
|
|
values[0] = y + h;
|
|
ConfigureWindow(nxagentViewportFrameBelow, mask, (XID *) &values, serverClient);
|
|
|
|
/*
|
|
* nxagentScreenTrap = False;
|
|
*/
|
|
}
|
|
|
|
#endif /* #ifdef VIEWPORT_FRAME */
|
|
|
|
void nxagentMoveViewport(ScreenPtr pScreen, int hShift, int vShift)
|
|
{
|
|
int newX, newY, oldX = 0, oldY = 0;
|
|
Bool doMove = False;
|
|
|
|
if (nxagentOption(Rootless))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* We must keep x coordinate between viewportXSpan and zero, if viewportXSpan
|
|
* is less then zero. If viewportXSpan is greater or equal to zero, it means
|
|
* the agent root window has a size smaller than the agent default window.
|
|
* In this case we keep the old coordinate.
|
|
*/
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentMoveViewport: RootX[%i] RootY[%i], hShift[%i] vShift[%i].\n",
|
|
nxagentOption(RootX), nxagentOption(RootY), hShift, vShift);
|
|
#endif
|
|
|
|
nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth));
|
|
nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight));
|
|
|
|
if (nxagentOption(ViewportXSpan) < 0)
|
|
{
|
|
newX = nxagentOption(RootX) - hShift;
|
|
|
|
if (newX > 0)
|
|
{
|
|
newX = 0;
|
|
}
|
|
else if (newX < nxagentOption(ViewportXSpan))
|
|
{
|
|
newX = nxagentOption(ViewportXSpan);
|
|
}
|
|
}
|
|
else if (nxagentOption(ViewportXSpan) == 0)
|
|
{
|
|
newX = 0;
|
|
}
|
|
else
|
|
{
|
|
newX = nxagentOption(RootX);
|
|
}
|
|
|
|
if (nxagentOption(ViewportYSpan) < 0)
|
|
{
|
|
newY = nxagentOption(RootY) - vShift;
|
|
|
|
if (newY > 0)
|
|
{
|
|
newY = 0;
|
|
}
|
|
else if (newY < nxagentOption(ViewportYSpan))
|
|
{
|
|
newY = nxagentOption(ViewportYSpan);
|
|
}
|
|
}
|
|
else if (nxagentOption(ViewportYSpan) == 0)
|
|
{
|
|
newY = 0;
|
|
}
|
|
else
|
|
{
|
|
newY = nxagentOption(RootY);
|
|
}
|
|
|
|
oldX = nxagentOption(RootX);
|
|
|
|
if (newX != nxagentOption(RootX))
|
|
{
|
|
nxagentChangeOption(RootX, newX);
|
|
|
|
doMove = True;
|
|
}
|
|
|
|
oldY = nxagentOption(RootY);
|
|
|
|
if (newY != nxagentOption(RootY))
|
|
{
|
|
nxagentChangeOption(RootY, newY);
|
|
|
|
doMove = True;
|
|
}
|
|
|
|
if (doMove)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentMoveViewport: New viewport geometry: (%d, %d)-"
|
|
"(%d, %d)\n", -nxagentOption(RootX), -nxagentOption(RootY),
|
|
-nxagentOption(RootX) + nxagentOption(Width),
|
|
-nxagentOption(RootY) + nxagentOption(Height));
|
|
|
|
fprintf(stderr, "nxagentMoveViewport: Root geometry x=[%d] y=[%d]\n",
|
|
pScreen->root -> drawable.x,
|
|
pScreen->root -> drawable.y );
|
|
#endif
|
|
|
|
XMoveWindow(nxagentDisplay, nxagentWindow(pScreen->root),
|
|
nxagentOption(RootX), nxagentOption(RootY));
|
|
|
|
if (nxagentOption(ClientOs) == ClientOsWinnt)
|
|
{
|
|
/*
|
|
* If doMove is True we add exposed rectangles to the remote
|
|
* expose region. This is done to refresh the areas showed newly
|
|
* in the viewport. We create two rectangles, one for
|
|
* horizontal pan and one for vertical pan.
|
|
*/
|
|
|
|
BoxRec hRect = {.x1 = -newX, .y1 = -newY};
|
|
|
|
if (hShift < 0)
|
|
{
|
|
hRect.x2 = -oldX;
|
|
hRect.y2 = -newY + nxagentOption(Height);
|
|
}
|
|
else if (hShift > 0)
|
|
{
|
|
hRect.x1 = -oldX + nxagentOption(Width);
|
|
hRect.x2 = -newX + nxagentOption(Width);
|
|
hRect.y2 = -newY + nxagentOption(Height);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentMoveViewport: hRect p1[%i, %i] - p2[%i, %i].\n", hRect.x1, hRect.y1, hRect.x2, hRect.y2);
|
|
#endif
|
|
|
|
BoxRec vRect = {.x1 = -newX, .y1 = -newY};
|
|
|
|
if (vShift < 0)
|
|
{
|
|
vRect.x2 = -newX + nxagentOption(Width);
|
|
vRect.y2 = -oldY;
|
|
}
|
|
else if (vShift > 0)
|
|
{
|
|
vRect.y1 = -oldY + nxagentOption(Height);
|
|
vRect.x2 = -newX + nxagentOption(Width);
|
|
vRect.y2 = -newY + nxagentOption(Height);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentMoveViewport: vRect p1[%i, %i] - p2[%i, %i].\n", vRect.x1, vRect.y1, vRect.x2, vRect.y2);
|
|
#endif
|
|
|
|
if (oldX != newX && hRect.x1 != hRect.x2 && hRect.y1 != hRect.y2)
|
|
{
|
|
nxagentAddRectToRemoteExposeRegion(&hRect);
|
|
}
|
|
|
|
if (oldY != newY && vRect.x1 != vRect.x2 && vRect.y1 != vRect.y2)
|
|
{
|
|
nxagentAddRectToRemoteExposeRegion(&vRect);
|
|
}
|
|
}
|
|
}
|
|
|
|
nxagentUpdateViewportFrame(-nxagentOption(RootX), -nxagentOption(RootY),
|
|
nxagentOption(Width), nxagentOption(Height));
|
|
}
|
|
|
|
/*
|
|
* This will update the window on the real X server by calling
|
|
* XConfigureWindow()/XMapWindow()/XLowerWindow()/XRaiseWindow().
|
|
* mask defines the values that need to be updated, see e.g.
|
|
* man XConfigureWindow.
|
|
*
|
|
* In addition to the bit flags known to Xorg it uses these
|
|
* self-defined ones: CW_Update, CW_Shape, CW_Map, CW_RootlessRestack.
|
|
*/
|
|
void nxagentConfigureWindow(WindowPtr pWin, unsigned int mask)
|
|
{
|
|
unsigned int valuemask;
|
|
XWindowChanges values;
|
|
int offX = nxagentWindowPriv(pWin)->x - pWin->origin.x;
|
|
int offY = nxagentWindowPriv(pWin)->y - pWin->origin.y;
|
|
|
|
if (nxagentScreenTrap)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentConfigureWindow: WARNING: Called with the screen trap set.\n");
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
if (nxagentOption(Rootless) &&
|
|
nxagentWindowTopLevel(pWin))
|
|
{
|
|
mask &= ~(CWSibling | CWStackMode);
|
|
}
|
|
else
|
|
{
|
|
if (mask & CW_RootlessRestack)
|
|
{
|
|
mask = CWStackMode;
|
|
}
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentConfigureWindow: Called with window [%p][%ld] and mask [%x].\n",
|
|
(void *) pWin, nxagentWindow(pWin), mask);
|
|
#endif
|
|
|
|
nxagentMoveCorruptedRegion(pWin, mask);
|
|
|
|
valuemask = 0;
|
|
|
|
if (mask & CW_Update)
|
|
{
|
|
mask |= CWX | CWY | CWWidth | CWHeight | CWBorderWidth | CWStackMode;
|
|
}
|
|
|
|
if (mask & CWX)
|
|
{
|
|
valuemask |= CWX;
|
|
values.x = nxagentWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
|
|
}
|
|
|
|
if (mask & CWY)
|
|
{
|
|
valuemask |= CWY;
|
|
values.y = nxagentWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
|
|
}
|
|
|
|
if (mask & CWWidth)
|
|
{
|
|
valuemask |= CWWidth;
|
|
values.width = nxagentWindowPriv(pWin)->width = pWin->drawable.width;
|
|
}
|
|
|
|
if (mask & CWHeight)
|
|
{
|
|
valuemask |= CWHeight;
|
|
values.height = nxagentWindowPriv(pWin)->height = pWin->drawable.height;
|
|
}
|
|
|
|
if (mask & CWBorderWidth)
|
|
{
|
|
valuemask |= CWBorderWidth;
|
|
values.border_width = nxagentWindowPriv(pWin)->borderWidth =
|
|
pWin->borderWidth;
|
|
}
|
|
|
|
if (mask & CW_Update)
|
|
{
|
|
valuemask = 0;
|
|
}
|
|
|
|
if (valuemask)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentConfigureWindow: Going to configure window [%p][%ld] with mask [%x].\n",
|
|
(void *) pWin, nxagentWindow(pWin), valuemask);
|
|
#endif
|
|
|
|
if (pWin->bitGravity == StaticGravity &&
|
|
((mask & CWX) || (mask & CWY)) &&
|
|
((mask & CWWidth) || (mask & CWHeight)))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentConfigureWindow: Window has StaticGravity. Going to translate Expose events by offset [%d, %d].\n",
|
|
offX, offY);
|
|
#endif
|
|
|
|
nxagentAddStaticResizedWindow(pWin, XNextRequest(nxagentDisplay), offX, offY);
|
|
|
|
for (int j = 0; j < nxagentExposeQueue.length; j++)
|
|
{
|
|
int i = (nxagentExposeQueue.start + j) % EXPOSED_SIZE;
|
|
|
|
if (nxagentExposeQueue.exposures[i].pWindow == pWin &&
|
|
nxagentExposeQueue.exposures[i].remoteRegion != NullRegion)
|
|
{
|
|
RegionTranslate(nxagentExposeQueue.exposures[i].remoteRegion, offX, offY);
|
|
}
|
|
}
|
|
}
|
|
|
|
XConfigureWindow(nxagentDisplay, nxagentWindow(pWin), valuemask, &values);
|
|
|
|
MAKE_SYNC_CONFIGURE_WINDOW;
|
|
}
|
|
|
|
if (mask & CWStackMode &&
|
|
nxagentWindowPriv(pWin)->siblingAbove != nxagentWindowSiblingAbove(pWin))
|
|
{
|
|
WindowPtr pSib;
|
|
|
|
/*
|
|
* Find the top sibling.
|
|
*/
|
|
|
|
for (pSib = pWin; pSib->prevSib != NullWindow; pSib = pSib->prevSib);
|
|
|
|
/*
|
|
* Configure the top sibling.
|
|
*/
|
|
|
|
valuemask = CWStackMode;
|
|
|
|
values.stack_mode = Above;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentConfigureWindow: Going to configure top sibling [%ld] "
|
|
"with mask [%x] and parent [%ld].\n", nxagentWindow(pSib),
|
|
valuemask, nxagentWindowParent(pWin));
|
|
#endif
|
|
|
|
XConfigureWindow(nxagentDisplay, nxagentWindow(pSib), valuemask, &values);
|
|
|
|
MAKE_SYNC_CONFIGURE_WINDOW;
|
|
|
|
nxagentWindowPriv(pSib)->siblingAbove = None;
|
|
|
|
/*
|
|
* Configure the rest of siblings.
|
|
*/
|
|
|
|
valuemask = CWSibling | CWStackMode;
|
|
|
|
values.stack_mode = Below;
|
|
|
|
for (pSib = pSib->nextSib; pSib != NullWindow; pSib = pSib->nextSib)
|
|
{
|
|
values.sibling = nxagentWindowSiblingAbove(pSib);
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentConfigureWindow: Going to configure other sibling [%ld] "
|
|
"with mask [%x] and parent [%ld] below [%ld].\n", nxagentWindow(pSib),
|
|
valuemask, nxagentWindowParent(pWin), nxagentWindowSiblingAbove(pSib));
|
|
#endif
|
|
|
|
XConfigureWindow(nxagentDisplay, nxagentWindow(pSib), valuemask, &values);
|
|
|
|
MAKE_SYNC_CONFIGURE_WINDOW;
|
|
|
|
nxagentWindowPriv(pSib)->siblingAbove = nxagentWindowSiblingAbove(pSib);
|
|
}
|
|
|
|
#ifdef TEST
|
|
{
|
|
Window root_return;
|
|
Window parent_return;
|
|
Window *children_return = NULL;
|
|
unsigned int nchildren_return;
|
|
|
|
Status result = XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
|
|
&root_return, &parent_return, &children_return, &nchildren_return);
|
|
|
|
if (result)
|
|
{
|
|
fprintf(stderr, "nxagentConfigureWindow: Children of the root: ");
|
|
while(nchildren_return > 0)
|
|
{
|
|
pSib = nxagentWindowPtr(children_return[--nchildren_return]);
|
|
if (pSib)
|
|
{
|
|
fprintf(stderr, "%lu ", children_return[nchildren_return]);
|
|
}
|
|
}
|
|
fprintf(stderr, "\n");
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "nxagentConfigureWindow: Failed QueryTree request.\n ");
|
|
}
|
|
|
|
SAFE_XFree(children_return);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* This should bring again the splash window
|
|
* on top, so why the else clause? Is this
|
|
* really needed?
|
|
*
|
|
*
|
|
* else if (mask & CWStackMode)
|
|
* {
|
|
* if (nxagentHaveSplashWindow())
|
|
* {
|
|
* valuemask = CWStackMode;
|
|
*
|
|
* values.stack_mode = Above;
|
|
*
|
|
* #ifdef TEST
|
|
* fprintf(stderr, "nxagentConfigureWindow: Going to configure splash window [%ld].\n",
|
|
* nxagentSplashWindow);
|
|
* #endif
|
|
*
|
|
* XConfigureWindow(nxagentDisplay, nxagentSplashWindow, valuemask, &values);
|
|
*
|
|
* MAKE_SYNC_CONFIGURE_WINDOW;
|
|
* }
|
|
* }
|
|
*/
|
|
|
|
if (mask & CW_RootlessRestack)
|
|
{
|
|
if (!pWin -> prevSib)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentConfigureWindow: Raising window [%p][%ld].\n",
|
|
(void *) pWin, nxagentWindow(pWin));
|
|
#endif
|
|
|
|
XRaiseWindow(nxagentDisplay, nxagentWindow(pWin));
|
|
}
|
|
else if (!pWin -> nextSib)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentConfigureWindow: Lowering window [%p][%ld].\n",
|
|
(void *) pWin, nxagentWindow(pWin));
|
|
#endif
|
|
|
|
XLowerWindow(nxagentDisplay, nxagentWindow(pWin));
|
|
}
|
|
else
|
|
{
|
|
XlibWindow windowList[2];
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentConfigureWindow: Putting window [%p][%ld] in the middle.\n",
|
|
(void *) pWin, nxagentWindow(pWin));
|
|
#endif
|
|
|
|
windowList[0] = nxagentWindow(pWin->prevSib);
|
|
windowList[1] = nxagentWindow(pWin);
|
|
|
|
XRestackWindows(nxagentDisplay, windowList, 2);
|
|
}
|
|
}
|
|
|
|
#ifdef SHAPE
|
|
if (mask & CW_Shape)
|
|
{
|
|
nxagentShapeWindow(pWin);
|
|
}
|
|
#endif
|
|
|
|
if (mask & CW_Map &&
|
|
(!nxagentOption(Rootless) ||
|
|
nxagentRootlessWindow != pWin))
|
|
{
|
|
XMapWindow(nxagentDisplay, nxagentWindow(pWin));
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* from "Definition of the Porting Layer for X v11 Sample Server":
|
|
*
|
|
* This function will be called when a window is reparented. At the
|
|
* time of the call, pWin will already be spliced into its new
|
|
* position in the window tree, and pPriorParent is its previous
|
|
* parent. This function can be NULL.
|
|
*
|
|
* We simply pass this over to the real X server.
|
|
*/
|
|
void nxagentReparentWindow(WindowPtr pWin, WindowPtr pOldParent)
|
|
{
|
|
if (nxagentScreenTrap)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentReparentWindow: window at %p [%lx] previous parent at %p [%lx].\n",
|
|
(void*)pWin, nxagentWindow(pWin),
|
|
(void*)pOldParent, nxagentWindow(pOldParent));
|
|
#endif
|
|
|
|
XReparentWindow(nxagentDisplay, nxagentWindow(pWin),
|
|
nxagentWindowParent(pWin),
|
|
pWin->origin.x - wBorderWidth(pWin),
|
|
pWin->origin.y - wBorderWidth(pWin));
|
|
}
|
|
|
|
/*
|
|
* from "Definition of the Porting Layer for X v11 Sample Server":
|
|
*
|
|
* ChangeWindowAttributes is called whenever DIX changes window
|
|
* attributes, such as the size, front-to-back ordering, title, or
|
|
* anything of lesser severity that affects the window itself. The
|
|
* sample server implements this routine. It computes accelerators for
|
|
* quickly putting up background and border tiles. (See description of
|
|
* the set of routines stored in the WindowRec.)
|
|
*/
|
|
Bool nxagentChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
|
|
{
|
|
XSetWindowAttributes attributes;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentChangeWindowAttributes: Changing attributes for window at [%p] with mask [%lu].\n",
|
|
(void *) pWin, mask);
|
|
#endif
|
|
|
|
if (nxagentScreenTrap)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
if (mask & CWBackPixmap)
|
|
{
|
|
switch (pWin->backgroundState)
|
|
{
|
|
case None:
|
|
{
|
|
attributes.background_pixmap = None;
|
|
attributes.background_pixel = nxagentWhitePixel;
|
|
|
|
/*
|
|
* One of problems faced during the implementation of lazy
|
|
* encoding policies was due to the presence of windows with
|
|
* transparent background, usually created by X clients to
|
|
* cover some sensible areas (i.e. checkboxes used by
|
|
* Konqueror 3.5). The sequence of operations consists in
|
|
* drawing the underneath part before covering it with the
|
|
* transparent window, so when we synchronize the deferred
|
|
* drawing operation we have to bear in mind that the dest-
|
|
* ination area is covered by a window. By using the Inclu-
|
|
* deInferiors GC's property and by clipping the region to
|
|
* synchronize to the borderClip instead of clipList (to
|
|
* include the areas covered by children) we can easily take
|
|
* care of this situation, but there is a drawback: if the
|
|
* children are not transparent, we are going to synchronize
|
|
* invisible areas. To avoid this we have added the 'has-
|
|
* TransparentChildren' flag, which is set when a window has
|
|
* at least one child with background None. The problem is
|
|
* that we don't know when to reset the flag. This solution,
|
|
* also, doesn't take care of transparent windows which don't
|
|
* have childhood relationships with underneath windows.
|
|
* We tried to mark the whole windows as dirty when they are
|
|
* created to force the synchronization of transparent windows
|
|
* with the content of underneath windows, but, of course,
|
|
* this works only with the first synchronization because the
|
|
* transparent windows will be never marked again as dirty.
|
|
*/
|
|
|
|
if (pWin -> parent != NULL)
|
|
{
|
|
nxagentWindowPriv(pWin -> parent) -> hasTransparentChildren = 1;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentChangeWindowAttributes: WARNING! Window at [%p] got the "
|
|
"hasTransparentChildren flag.\n", (void *) pWin);
|
|
#endif
|
|
}
|
|
|
|
break;
|
|
}
|
|
case ParentRelative:
|
|
{
|
|
attributes.background_pixmap = ParentRelative;
|
|
break;
|
|
}
|
|
case BackgroundPixmap:
|
|
{
|
|
/*
|
|
* If a window background is corrupted, we grant its usability
|
|
* by clearing it with a solid color. When the pixmap will be
|
|
* fully synchronized, an expose will be sent to the window's
|
|
* hierarchy.
|
|
*/
|
|
|
|
if (nxagentDrawableStatus((DrawablePtr) pWin -> background.pixmap) == NotSynchronized)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentChangeWindowAttributes: The window at [%p] has the background at [%p] "
|
|
"not synchronized.\n", (void *) pWin, (void *) pWin -> background.pixmap);
|
|
#endif
|
|
|
|
if (nxagentIsCorruptedBackground(pWin -> background.pixmap) == 0)
|
|
{
|
|
nxagentIsCorruptedBackground(pWin -> background.pixmap) = 1;
|
|
|
|
nxagentAllocateCorruptedResource((DrawablePtr) pWin -> background.pixmap, RT_NX_CORR_BACKGROUND);
|
|
|
|
/*
|
|
* Clearing the remote background to make it usable.
|
|
*/
|
|
|
|
nxagentFillRemoteRegion((DrawablePtr) pWin -> background.pixmap,
|
|
nxagentCorruptedRegion((DrawablePtr) pWin -> background.pixmap));
|
|
}
|
|
}
|
|
|
|
attributes.background_pixmap = nxagentPixmap(pWin -> background.pixmap);
|
|
|
|
break;
|
|
}
|
|
case BackgroundPixel:
|
|
{
|
|
mask &= ~CWBackPixmap;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mask & CWBackPixel)
|
|
{
|
|
if (pWin -> backgroundState == BackgroundPixel)
|
|
{
|
|
attributes.background_pixel = nxagentPixel(pWin -> background.pixel);
|
|
}
|
|
else
|
|
{
|
|
mask &= ~CWBackPixel;
|
|
}
|
|
}
|
|
|
|
if (mask & CWBorderPixmap)
|
|
{
|
|
if (pWin -> borderIsPixel != 0)
|
|
{
|
|
mask &= ~CWBorderPixmap;
|
|
}
|
|
else
|
|
{
|
|
attributes.border_pixmap = nxagentPixmap(pWin -> border.pixmap);
|
|
}
|
|
}
|
|
|
|
if (mask & CWBorderPixel)
|
|
{
|
|
if (pWin -> borderIsPixel != 0)
|
|
{
|
|
attributes.border_pixel = nxagentPixel(pWin -> border.pixel);
|
|
}
|
|
else
|
|
{
|
|
mask &= ~CWBorderPixel;
|
|
}
|
|
}
|
|
|
|
if (mask & CWBitGravity)
|
|
{
|
|
attributes.bit_gravity = pWin -> bitGravity;
|
|
}
|
|
|
|
/*
|
|
* As we set this bit, we must change dix in order not to perform
|
|
* PositionWindow and let X move children windows for us.
|
|
*/
|
|
|
|
if (mask & CWWinGravity)
|
|
{
|
|
attributes.win_gravity = pWin -> winGravity;
|
|
}
|
|
|
|
/*
|
|
FIXME: Do we need to set the attribute on the remote display?
|
|
*/
|
|
if (mask & CWBackingStore)
|
|
{
|
|
attributes.backing_store = pWin -> backingStore;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentChangeWindowAttributes: Changing backing store value to %d"
|
|
" for window at %p.\n", pWin -> backingStore, (void*)pWin);
|
|
#endif
|
|
}
|
|
|
|
if (mask & CWBackingPlanes)
|
|
{
|
|
if ((nxagentBackingStore == NotUseful) || (pWin -> optional == NULL))
|
|
{
|
|
mask &= ~CWBackingPlanes;
|
|
}
|
|
else
|
|
{
|
|
attributes.backing_planes = pWin -> optional -> backingBitPlanes;
|
|
}
|
|
}
|
|
|
|
if (mask & CWBackingPixel)
|
|
{
|
|
if ((nxagentBackingStore == NotUseful) || (pWin -> optional == NULL))
|
|
{
|
|
mask &= ~CWBackingPixel;
|
|
}
|
|
else
|
|
{
|
|
attributes.backing_pixel = pWin -> optional -> backingPixel;
|
|
}
|
|
}
|
|
|
|
if (mask & CWOverrideRedirect)
|
|
{
|
|
attributes.override_redirect = pWin -> overrideRedirect;
|
|
}
|
|
|
|
/*
|
|
FIXME: Do we need to set the attribute on the remote display?
|
|
*/
|
|
if (mask & CWSaveUnder)
|
|
{
|
|
attributes.save_under = pWin -> saveUnder;
|
|
}
|
|
|
|
/*
|
|
* Events are handled elsewhere.
|
|
*/
|
|
|
|
if (mask & CWEventMask)
|
|
{
|
|
mask &= ~CWEventMask;
|
|
}
|
|
|
|
if (mask & CWDontPropagate)
|
|
{
|
|
mask &= ~CWDontPropagate;
|
|
}
|
|
|
|
if (mask & CWColormap)
|
|
{
|
|
ColormapPtr pCmap = (ColormapPtr) LookupIDByType(wColormap(pWin), RT_COLORMAP);
|
|
|
|
/*
|
|
FIXME: When the caller is nxagentReconfigureWindow sometimes
|
|
wColormap(pWin) is 0. Could a window have no colormap?
|
|
*/
|
|
if (pCmap != NULL)
|
|
{
|
|
attributes.colormap = nxagentColormap(pCmap);
|
|
|
|
nxagentSetInstalledColormapWindows(pWin -> drawable.pScreen);
|
|
}
|
|
else
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentChangeWindowAttributes: WARNING! Bad colormap "
|
|
"[%lu] for window at [%p].\n", wColormap(pWin), (void *) pWin);
|
|
#endif
|
|
|
|
mask &= ~CWColormap;
|
|
}
|
|
}
|
|
|
|
if (mask & CWCursor)
|
|
{
|
|
if (nxagentOption(Rootless))
|
|
{
|
|
if (pWin->cursorIsNone == 0 && pWin->optional != NULL &&
|
|
pWin->optional->cursor != NULL && nxagentCursorPriv(pWin ->
|
|
optional -> cursor, pWin -> drawable.pScreen) != NULL)
|
|
{
|
|
attributes.cursor = nxagentCursor(pWin -> optional -> cursor,
|
|
pWin -> drawable.pScreen);
|
|
}
|
|
else
|
|
{
|
|
attributes.cursor = None;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* This is handled in cursor code
|
|
*/
|
|
|
|
mask &= ~CWCursor;
|
|
}
|
|
}
|
|
|
|
if (mask != 0)
|
|
{
|
|
XChangeWindowAttributes(nxagentDisplay, nxagentWindow(pWin), mask, &attributes);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* Set the WM_STATE property of pWin to the desired value */
|
|
void nxagentSetWMState(WindowPtr pWin, CARD32 desired)
|
|
{
|
|
Atom prop = MakeAtom("WM_STATE", strlen("WM_STATE"), True);
|
|
nxagentWMStateRec wmState = {.state = desired, .icon = None};
|
|
if (ChangeWindowProperty(pWin, prop, prop, 32, 0, 2, &wmState, 1) != Success)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "%s: Changing WM_STATE failed.\n", __func__);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*
|
|
* from "Definition of the Porting Layer for X v11 Sample Server":
|
|
*
|
|
* RealizeWindow/UnRealizeWindow:
|
|
* These routines are hooks for when DIX maps (makes visible) and
|
|
* unmaps (makes invisible) a window. It should do whatever private
|
|
* operations need to be done when these happen, such as allocating or
|
|
* deallocating structures that are only needed for visible
|
|
* windows. RealizeWindow does NOT draw the window border, background
|
|
* or contents; UnrealizeWindow does NOT erase the window or generate
|
|
* exposure events for underlying windows; this is taken care of by
|
|
* DIX. DIX does, however, call PaintWindowBackground() and
|
|
* PaintWindowBorder() to perform some of these.
|
|
-+ */
|
|
Bool nxagentRealizeWindow(WindowPtr pWin)
|
|
{
|
|
if (nxagentScreenTrap)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
/*
|
|
* Not needed.
|
|
*
|
|
* nxagentConfigureWindow(pWin, CWStackMode);
|
|
*
|
|
* nxagentFlushConfigureWindow();
|
|
*/
|
|
|
|
nxagentAddConfiguredWindow(pWin, CWStackMode);
|
|
nxagentAddConfiguredWindow(pWin, CW_Shape);
|
|
|
|
/* add by dimbor */
|
|
if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin))
|
|
{
|
|
nxagentSetWMState(pWin, NormalState);
|
|
}
|
|
|
|
/*
|
|
* Not needed.
|
|
*
|
|
#ifdef SHAPE
|
|
nxagentShapeWindow(pWin);
|
|
#endif
|
|
*/
|
|
|
|
#ifdef TEST
|
|
if (nxagentOption(Rootless) && nxagentLastWindowDestroyed)
|
|
{
|
|
fprintf(stderr, "%s: Window realized. Stopped termination for rootless session.\n", __func__);
|
|
}
|
|
#endif
|
|
|
|
nxagentAddConfiguredWindow(pWin, CW_Map);
|
|
|
|
nxagentLastWindowDestroyed = False;
|
|
|
|
return True;
|
|
}
|
|
|
|
/* See nxagentRealizeWindow for a description */
|
|
Bool nxagentUnrealizeWindow(WindowPtr pWin)
|
|
{
|
|
if (nxagentScreenTrap)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
/* add by dimbor */
|
|
if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin))
|
|
{
|
|
/*
|
|
* The original _comment_ was WithdrawnState, while the _value_
|
|
* was 3, which is IconicState.
|
|
*/
|
|
nxagentSetWMState(pWin, IconicState);
|
|
}
|
|
|
|
XUnmapWindow(nxagentDisplay, nxagentWindow(pWin));
|
|
|
|
return True;
|
|
}
|
|
|
|
void nxagentFrameBufferPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
|
|
{
|
|
if (pWin->backgroundState == BackgroundPixmap)
|
|
{
|
|
pWin->background.pixmap = nxagentVirtualPixmap(pWin->background.pixmap);
|
|
}
|
|
|
|
if (pWin->borderIsPixel == False)
|
|
{
|
|
pWin->border.pixmap = nxagentVirtualPixmap(pWin->border.pixmap);
|
|
}
|
|
|
|
/*
|
|
* Call fbPaintWindow(). We need to temporarily replace
|
|
* PaintWindowBackground() by ourself because fbPaintWindow() is
|
|
* recursively calling it for parent windows, too.
|
|
*/
|
|
{
|
|
void (*PaintWindowBackgroundBackup)(WindowPtr, RegionPtr, int);
|
|
|
|
PaintWindowBackgroundBackup = pWin->drawable.pScreen -> PaintWindowBackground;
|
|
|
|
pWin->drawable.pScreen -> PaintWindowBackground = nxagentFrameBufferPaintWindow;
|
|
|
|
fbPaintWindow(pWin, pRegion, what);
|
|
|
|
pWin->drawable.pScreen -> PaintWindowBackground = PaintWindowBackgroundBackup;
|
|
}
|
|
|
|
if (pWin->backgroundState == BackgroundPixmap)
|
|
{
|
|
pWin->background.pixmap = nxagentRealPixmap(pWin->background.pixmap);
|
|
}
|
|
|
|
if (pWin->borderIsPixel == False)
|
|
{
|
|
pWin->border.pixmap = nxagentRealPixmap(pWin->border.pixmap);
|
|
}
|
|
}
|
|
|
|
void nxagentPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what)
|
|
{
|
|
if (pWin -> realized)
|
|
{
|
|
BoxPtr pBox = RegionRects(pRegion);
|
|
|
|
for (int i = 0; i < RegionNumRects(pRegion); i++)
|
|
{
|
|
XClearArea(nxagentDisplay, nxagentWindow(pWin),
|
|
pBox[i].x1 - pWin->drawable.x,
|
|
pBox[i].y1 - pWin->drawable.y,
|
|
pBox[i].x2 - pBox[i].x1,
|
|
pBox[i].y2 - pBox[i].y1,
|
|
False);
|
|
}
|
|
}
|
|
#ifdef TEST
|
|
else
|
|
{
|
|
fprintf(stderr, "nxagentPaintWindowBackground: Saving the operation with window "
|
|
"at [%p] not realized.\n", (void *) pWin);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* The framebuffer operations don't take care of clipping to the
|
|
* actual area of the framebuffer so we need to clip ourselves.
|
|
*/
|
|
|
|
RegionRec temp;
|
|
RegionInit(&temp, NullBox, 1);
|
|
RegionIntersect(&temp, pRegion, &pWin -> clipList);
|
|
nxagentFrameBufferPaintWindow(pWin, &temp, what);
|
|
RegionUninit(&temp);
|
|
}
|
|
|
|
void nxagentPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what)
|
|
{
|
|
/*
|
|
* The framebuffer operations don't take care of clipping to the
|
|
* actual area of the framebuffer so we need to clip ourselves.
|
|
*/
|
|
|
|
RegionRec temp;
|
|
RegionInit(&temp, NullBox, 1);
|
|
RegionIntersect(&temp, pRegion, &pWin -> borderClip);
|
|
nxagentFrameBufferPaintWindow(pWin, &temp, what);
|
|
RegionUninit(&temp);
|
|
}
|
|
|
|
/*
|
|
* from "Definition of the Porting Layer for X v11 Sample Server":
|
|
*
|
|
* CopyWindow is called when a window is moved, and graphically moves
|
|
* to pixels of a window on the screen. It should not change any other
|
|
* state within DDX (see PositionWindow(), above).
|
|
*
|
|
* oldpt is the old location of the upper-left corner. oldRegion is
|
|
* the old region it is coming from. The new location and new region
|
|
* is stored in the WindowRec. oldRegion might modified in place by
|
|
* this routine (the sample implementation does this).
|
|
*
|
|
* CopyArea could be used, except that this operation has more
|
|
* complications. First of all, you do not want to copy a rectangle
|
|
* onto a rectangle. The original window may be obscured by other
|
|
* windows, and the new window location may be similarly
|
|
* obscured. Second, some hardware supports multiple windows with
|
|
* multiple depths, and your routine needs to take care of that.
|
|
*
|
|
* The pixels in oldRegion (with reference point oldpt) are copied to
|
|
* the window's new region (pWin->borderClip). pWin->borderClip is
|
|
* gotten directly from the window, rather than passing it as a
|
|
* parameter.
|
|
*
|
|
* The sample server implementation is in Xserver/fb/fbwindow.c.
|
|
*/
|
|
void nxagentCopyWindow(WindowPtr pWin, xPoint oldOrigin, RegionPtr oldRegion)
|
|
{
|
|
fbCopyWindow(pWin, oldOrigin, oldRegion);
|
|
}
|
|
|
|
/*
|
|
* from "Definition of the Porting Layer for X v11 Sample Server":
|
|
*
|
|
* Whenever the cliplist for a window is changed, this function is
|
|
* called to perform whatever hardware manipulations might be
|
|
* necessary. When called, the clip list and border clip regions in
|
|
* the window are set to the new values. dx,dy are the distance that
|
|
* the window has been moved (if at all).
|
|
*/
|
|
void nxagentClipNotify(WindowPtr pWin, int dx, int dy)
|
|
{
|
|
/*
|
|
* nxagentConfigureWindow(pWin, CWStackMode);
|
|
*/
|
|
|
|
nxagentAddConfiguredWindow(pWin, CWStackMode);
|
|
nxagentAddConfiguredWindow(pWin, CW_Shape);
|
|
|
|
#ifdef SHAPE
|
|
/*
|
|
* nxagentShapeWindow(pWin);
|
|
*/
|
|
#endif /* SHAPE */
|
|
}
|
|
|
|
/*
|
|
* from "Definition of the Porting Layer for X v11 Sample Server":
|
|
*
|
|
* The WindowExposures() routine paints the border and generates
|
|
* exposure events for the window. pRegion is an unoccluded region of
|
|
* the window, and pBSRegion is an occluded region that has backing
|
|
* store. Since exposure events include a rectangle describing what
|
|
* was exposed, this routine may have to send back a series of
|
|
* exposure events, one for each rectangle of the region. The count
|
|
* field in the expose event is a hint to the client as to the number
|
|
* of regions that are after this one. This routine must be
|
|
* provided. The sample server has a machine-independent version in
|
|
* Xserver/mi/miexpose.c.
|
|
*/
|
|
void nxagentWindowExposures(WindowPtr pWin, RegionPtr pRgn, RegionPtr other_exposed)
|
|
{
|
|
/*
|
|
* The problem: we want to synthetize the expose events internally, so
|
|
* that we reduce the time between a window operation and the corresp-
|
|
* onding graphical output, but at the same time we need to take care
|
|
* of the remote exposures, as we need to handle those cases where our
|
|
* windows are covered by the windows on the real display. Handling
|
|
* both the local and the remote exposures we would generate the same
|
|
* redraws twice, something we call "double refreshes", so we must be
|
|
* able to identify which events have been already sent to our clients.
|
|
*
|
|
* Here is how the algorithm is working:
|
|
*
|
|
* - We collect the exposures that the agent sent to its clients in a
|
|
* region (the "local-region") and store the region for a given win-
|
|
* dow in a vector.
|
|
*
|
|
* - Another region collects the expose that were received from the
|
|
* real X server (the "remote-region") for the same window.
|
|
*
|
|
* - We create a "fake" off-screen window. For every generated region
|
|
* we send a ConfigureWindow request for that window to synchronize
|
|
* ourselves with both the remote X server and/or the window manager.
|
|
*
|
|
* - When the ConfigureNotify is received, we calculate the difference
|
|
* between the "remote-region" and the "local-region" for the window
|
|
* that had collected exposures.
|
|
*
|
|
* - Finally we send the resulting exposures to our clients.
|
|
*
|
|
* As you may have guessed, the windows are synchronized per-region,
|
|
* that is there is a single region for a set of exposures. The regions
|
|
* are handled in order. This means that we can always calculate the
|
|
* final region by referring to the first element of the vector.
|
|
*/
|
|
|
|
|
|
if (nxagentSessionState != SESSION_DOWN)
|
|
{
|
|
if (!nxagentExposeArrayIsInitialized)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentWindowExposures: Initializing expose queue.\n");
|
|
#endif
|
|
|
|
for (int i = 0; i < EXPOSED_SIZE; i++)
|
|
{
|
|
nxagentExposeQueue.exposures[i].pWindow = NULL;
|
|
nxagentExposeQueue.exposures[i].localRegion = NullRegion;
|
|
nxagentExposeQueue.exposures[i].remoteRegion = NullRegion;
|
|
nxagentExposeQueue.exposures[i].remoteRegionIsCompleted = False;
|
|
nxagentExposeQueue.exposures[i].serial = 0;
|
|
}
|
|
|
|
nxagentExposeQueue.start = 0;
|
|
nxagentExposeQueue.length = 0;
|
|
nxagentExposeSerial = 0;
|
|
|
|
XSetWindowAttributes attributes = {.event_mask = StructureNotifyMask};
|
|
nxagentConfiguredSynchroWindow = XCreateWindow(nxagentDisplay, DefaultRootWindow(nxagentDisplay), 0, 0,
|
|
1, 1, 0, 0, InputOutput, 0, CWEventMask, &attributes);
|
|
|
|
nxagentInitRemoteExposeRegion();
|
|
|
|
nxagentExposeArrayIsInitialized = True;
|
|
}
|
|
|
|
RegionRec temp;
|
|
RegionInit(&temp, (BoxRec *) NULL, 1);
|
|
|
|
if (pRgn != NULL)
|
|
{
|
|
if (RegionNumRects(pRgn) > RECTLIMIT)
|
|
{
|
|
BoxRec box = *RegionExtents(pRgn);
|
|
|
|
RegionEmpty(pRgn);
|
|
RegionInit(pRgn, &box, 1);
|
|
}
|
|
|
|
RegionUnion(&temp, &temp, pRgn);
|
|
}
|
|
|
|
if (other_exposed != NULL)
|
|
{
|
|
RegionUnion(&temp, &temp, other_exposed);
|
|
}
|
|
|
|
if (!RegionNil(&temp))
|
|
{
|
|
RegionTranslate(&temp,
|
|
-(pWin -> drawable.x), -(pWin -> drawable.y));
|
|
|
|
if (nxagentExposeQueue.length < EXPOSED_SIZE)
|
|
{
|
|
int index = (nxagentExposeQueue.start + nxagentExposeQueue.length) % EXPOSED_SIZE;
|
|
|
|
nxagentExposeQueue.exposures[index].pWindow = pWin;
|
|
nxagentExposeQueue.exposures[index].localRegion = RegionCreate(NULL, 1);
|
|
|
|
if (nxagentOption(Rootless) && nxagentWindowPriv(pWin) &&
|
|
(nxagentWindowPriv(pWin) -> isMapped == 0 ||
|
|
nxagentWindowPriv(pWin) -> visibilityState != VisibilityUnobscured))
|
|
{
|
|
nxagentExposeQueue.exposures[index].remoteRegion = RegionCreate(NULL, 1);
|
|
|
|
RegionUnion(nxagentExposeQueue.exposures[index].remoteRegion,
|
|
nxagentExposeQueue.exposures[index].remoteRegion, &temp);
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentWindowExposures: Added region to remoteRegion for window [%ld] to position [%d].\n",
|
|
nxagentWindow(pWin), nxagentExposeQueue.length);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
RegionUnion(nxagentExposeQueue.exposures[index].localRegion,
|
|
nxagentExposeQueue.exposures[index].localRegion, &temp);
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentWindowExposures: Added region to localRegion for window [%ld] to position [%d].\n",
|
|
nxagentWindow(pWin), nxagentExposeQueue.length);
|
|
#endif
|
|
}
|
|
|
|
nxagentExposeSerial = (nxagentExposeSerial - 1) % EXPOSED_SIZE;
|
|
|
|
nxagentExposeQueue.exposures[index].serial = nxagentExposeSerial;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentWindowExposures: Added region to queue with serial [%d].\n", nxagentExposeSerial);
|
|
#endif
|
|
|
|
/*
|
|
* Mark this region for sending a synchro, in
|
|
* nxagentFlushConfigureWindow().
|
|
*/
|
|
|
|
nxagentExposeQueue.exposures[index].synchronize = 1;
|
|
nxagentExposeQueue.length++;
|
|
|
|
if (nxagentOption(Rootless) && nxagentWindowPriv(pWin) &&
|
|
(nxagentWindowPriv(pWin) -> isMapped == 0 ||
|
|
nxagentWindowPriv(pWin) -> visibilityState != VisibilityUnobscured))
|
|
{
|
|
RegionUninit(&temp);
|
|
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RegionUninit(&temp);
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentWindowExposures: WARNING! Reached maximum size of collect exposures vector.\n");
|
|
#endif
|
|
|
|
if ((pRgn != NULL && RegionNotEmpty(pRgn) != 0) ||
|
|
(other_exposed != NULL && RegionNotEmpty(other_exposed) != 0))
|
|
{
|
|
nxagentUnmarkExposedRegion(pWin, pRgn, other_exposed);
|
|
|
|
miWindowExposures(pWin, pRgn, other_exposed);
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
RegionUninit(&temp);
|
|
}
|
|
|
|
if ((pRgn != NULL && RegionNotEmpty(pRgn) != 0) ||
|
|
(other_exposed != NULL && RegionNotEmpty(other_exposed) != 0))
|
|
{
|
|
nxagentUnmarkExposedRegion(pWin, pRgn, other_exposed);
|
|
|
|
miWindowExposures(pWin, pRgn, other_exposed);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#ifdef SHAPE
|
|
static Bool nxagentRegionEqual(RegionPtr pReg1, RegionPtr pReg2)
|
|
{
|
|
if (pReg1 == pReg2)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
if (pReg1 == NullRegion || pReg2 == NullRegion)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
BoxPtr pBox1 = RegionRects(pReg1);
|
|
int n1 = RegionNumRects(pReg1);
|
|
|
|
BoxPtr pBox2 = RegionRects(pReg2);
|
|
int n2 = RegionNumRects(pReg2);
|
|
|
|
if (n1 != n2)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
if (pBox1 == pBox2)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
if (memcmp(pBox1, pBox2, n1 * sizeof(BoxRec)))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
void nxagentShapeWindow(WindowPtr pWin)
|
|
{
|
|
if (NXDisplayError(nxagentDisplay) == 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentShapeWindow: Window at [%p][%ld].\n",
|
|
(void *) pWin, nxagentWindow(pWin));
|
|
#endif
|
|
|
|
/*
|
|
FIXME: this is the same code as below, just with another shape. Maybe move
|
|
this code to a helper function?
|
|
*/
|
|
if (!nxagentRegionEqual(nxagentWindowPriv(pWin)->boundingShape,
|
|
wBoundingShape(pWin)))
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentShapeWindow: Bounding shape differs.\n");
|
|
#endif
|
|
|
|
if (wBoundingShape(pWin))
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentShapeWindow: wBounding shape has [%ld] rects.\n",
|
|
RegionNumRects(wBoundingShape(pWin)));
|
|
#endif
|
|
|
|
if (!nxagentWindowPriv(pWin)->boundingShape)
|
|
{
|
|
nxagentWindowPriv(pWin)->boundingShape = RegionCreate(NULL, 1);
|
|
}
|
|
|
|
RegionCopy(nxagentWindowPriv(pWin)->boundingShape, wBoundingShape(pWin));
|
|
|
|
Region reg = XCreateRegion();
|
|
BoxPtr pBox = RegionRects(nxagentWindowPriv(pWin)->boundingShape);
|
|
for (int i = 0;
|
|
i < RegionNumRects(nxagentWindowPriv(pWin)->boundingShape);
|
|
i++)
|
|
{
|
|
XRectangle rect = {
|
|
.x = pBox[i].x1,
|
|
.y = pBox[i].y1,
|
|
.width = pBox[i].x2 - pBox[i].x1,
|
|
.height = pBox[i].y2 - pBox[i].y1
|
|
};
|
|
XUnionRectWithRegion(&rect, reg, reg);
|
|
}
|
|
|
|
XShapeCombineRegion(nxagentDisplay, nxagentWindow(pWin),
|
|
ShapeBounding, 0, 0, reg, ShapeSet);
|
|
|
|
XDestroyRegion(reg);
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentShapeWindow: wBounding shape does not exist. Removing the shape.\n");
|
|
#endif
|
|
|
|
RegionEmpty(nxagentWindowPriv(pWin)->boundingShape);
|
|
|
|
XShapeCombineMask(nxagentDisplay, nxagentWindow(pWin),
|
|
ShapeBounding, 0, 0, None, ShapeSet);
|
|
}
|
|
}
|
|
|
|
if (!nxagentRegionEqual(nxagentWindowPriv(pWin)->clipShape, wClipShape(pWin)))
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentShapeWindow: Clip shape differs.\n");
|
|
#endif
|
|
|
|
if (wClipShape(pWin))
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentShapeWindow: wClip shape has [%ld] rects.\n",
|
|
RegionNumRects(wClipShape(pWin)));
|
|
#endif
|
|
|
|
if (!nxagentWindowPriv(pWin)->clipShape)
|
|
{
|
|
nxagentWindowPriv(pWin)->clipShape = RegionCreate(NULL, 1);
|
|
}
|
|
|
|
RegionCopy(nxagentWindowPriv(pWin)->clipShape, wClipShape(pWin));
|
|
|
|
Region reg = XCreateRegion();
|
|
BoxPtr pBox = RegionRects(nxagentWindowPriv(pWin)->clipShape);
|
|
for (int i = 0;
|
|
i < RegionNumRects(nxagentWindowPriv(pWin)->clipShape);
|
|
i++)
|
|
{
|
|
XRectangle rect = {
|
|
.x = pBox[i].x1,
|
|
.y = pBox[i].y1,
|
|
.width = pBox[i].x2 - pBox[i].x1,
|
|
.height = pBox[i].y2 - pBox[i].y1
|
|
};
|
|
XUnionRectWithRegion(&rect, reg, reg);
|
|
}
|
|
|
|
XShapeCombineRegion(nxagentDisplay, nxagentWindow(pWin),
|
|
ShapeClip, 0, 0, reg, ShapeSet);
|
|
|
|
XDestroyRegion(reg);
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentShapeWindow: wClip shape does not exist. Removing the shape.\n");
|
|
#endif
|
|
|
|
RegionEmpty(nxagentWindowPriv(pWin)->clipShape);
|
|
|
|
XShapeCombineMask(nxagentDisplay, nxagentWindow(pWin),
|
|
ShapeClip, 0, 0, None, ShapeSet);
|
|
}
|
|
}
|
|
}
|
|
#endif /* SHAPE */
|
|
|
|
static int nxagentForceExposure(WindowPtr pWin, void * ptr)
|
|
{
|
|
if (pWin -> drawable.class != InputOnly)
|
|
{
|
|
WindowPtr pRoot = pWin->drawable.pScreen->root;
|
|
BoxRec Box = {
|
|
.x1 = pWin->drawable.x,
|
|
.y1 = pWin->drawable.y,
|
|
.x2 = Box.x1 + pWin->drawable.width,
|
|
.y2 = Box.y1 + pWin->drawable.height,
|
|
};
|
|
RegionPtr exposedRgn = RegionCreate(&Box, 1);
|
|
|
|
RegionIntersect(exposedRgn, exposedRgn, &pRoot->winSize);
|
|
|
|
if (exposedRgn != NULL && RegionNotEmpty(exposedRgn) != 0)
|
|
{
|
|
miWindowExposures(pWin, exposedRgn, NullRegion);
|
|
}
|
|
|
|
RegionDestroy(exposedRgn);
|
|
}
|
|
|
|
return WT_WALKCHILDREN;
|
|
}
|
|
|
|
void nxagentRefreshWindows(WindowPtr pWin)
|
|
{
|
|
int action = 1;
|
|
|
|
TraverseTree(pWin, nxagentForceExposure, &action);
|
|
}
|
|
|
|
void nxagentUnmapWindows(void)
|
|
{
|
|
if (nxagentOption(Fullscreen))
|
|
{
|
|
for (int i = 0; i < screenInfo.numScreens; i++)
|
|
{
|
|
if (nxagentDefaultWindows[i])
|
|
{
|
|
XUnmapWindow(nxagentDisplay, nxagentDefaultWindows[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
NXFlushDisplay(nxagentDisplay, NXFlushLink);
|
|
}
|
|
|
|
void nxagentMapDefaultWindows(void)
|
|
{
|
|
for (int i = 0; i < screenInfo.numScreens; i++)
|
|
{
|
|
WindowPtr pWin = screenInfo.screens[i]->root;
|
|
ScreenPtr pScreen = pWin -> drawable.pScreen;
|
|
|
|
/*
|
|
* InitRootWindow does that already, but as MapWindow() is
|
|
* idempotent we keep it here, too
|
|
*/
|
|
MapWindow(pWin, serverClient);
|
|
|
|
if (!nxagentOption(Rootless))
|
|
{
|
|
/*
|
|
* Show the NX splash screen.
|
|
*/
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentMapDefaultWindows: Showing the splash window.\n");
|
|
#endif
|
|
|
|
nxagentShowSplashWindow(nxagentDefaultWindows[pScreen->myNum]);
|
|
|
|
/*
|
|
* Map the default window. Defer the mapping if the session is
|
|
* of shadow type. If no WM is running on the remote display,
|
|
* map the window soon anyway: this avoids a flickering effect
|
|
* on the !M logo if the shadow session is displayed from a
|
|
* Windows client.
|
|
*/
|
|
|
|
if (!nxagentOption(Shadow) || !nxagentWMIsRunning)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentMapDefaultWindows: Mapping default window id [%ld].\n",
|
|
nxagentDefaultWindows[pScreen->myNum]);
|
|
#endif
|
|
|
|
XMapWindow(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum]);
|
|
|
|
if (nxagentOption(Fullscreen) && nxagentWMIsRunning)
|
|
{
|
|
nxagentMaximizeToFullScreen(pScreen);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Map and raise the input window.
|
|
*/
|
|
|
|
XMapWindow(nxagentDisplay, nxagentInputWindows[pScreen->myNum]);
|
|
|
|
/*
|
|
* At reconnection the Input Window is raised in
|
|
* nxagentReconnectAllWindows, after the Root Window is mapped.
|
|
*/
|
|
|
|
if (!nxagentReconnectTrap)
|
|
{
|
|
XRaiseWindow(nxagentDisplay, nxagentInputWindows[pScreen->myNum]);
|
|
}
|
|
}
|
|
|
|
#ifdef NXAGENT_ONSTART
|
|
/*
|
|
* Send a SetSelectionOwner request to notify of the agent start.
|
|
*/
|
|
|
|
XSetSelectionOwner(nxagentDisplay, serverTransToAgentProperty,
|
|
nxagentDefaultWindows[i], CurrentTime);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Map the icon window.
|
|
*/
|
|
|
|
if (nxagentIconWindow != None)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentMapDefaultWindows: Mapping icon window id [%ld].\n",
|
|
nxagentIconWindow);
|
|
#endif
|
|
|
|
XMapWindow(nxagentDisplay, nxagentIconWindow);
|
|
}
|
|
|
|
/*
|
|
* Ensure that the fullscreen window gets the focus.
|
|
*/
|
|
|
|
if (nxagentFullscreenWindow != None)
|
|
{
|
|
XSetInputFocus(nxagentDisplay, nxagentFullscreenWindow,
|
|
RevertToParent, CurrentTime);
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentMapDefaultWindows: Completed mapping of default windows.\n");
|
|
#endif
|
|
}
|
|
|
|
Bool nxagentDisconnectAllWindows(void)
|
|
{
|
|
Bool succeeded = True;
|
|
|
|
#if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_WINDOW_DEBUG)
|
|
fprintf(stderr, "nxagentDisconnectAllWindows\n");
|
|
#endif
|
|
|
|
for (int i = 0; i < screenInfo.numScreens; i++)
|
|
{
|
|
nxagentTraverseWindow(screenInfo.screens[i]->root, nxagentDisconnectWindow, &succeeded);
|
|
nxagentDefaultWindows[i] = None;
|
|
}
|
|
|
|
#ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
|
|
fprintf(stderr, "nxagentDisconnectAllWindows: all windows disconnected\n");
|
|
#endif
|
|
|
|
return succeeded;
|
|
}
|
|
|
|
/*
|
|
* FIXME: We are giving up reconnecting those void *
|
|
* that are not resource, and we are just disconnecting them.
|
|
* Perhaps we could do better and reconnect them.
|
|
*/
|
|
|
|
void nxagentDisconnectWindow(void * p0, XID x1, void * p2)
|
|
{
|
|
WindowPtr pWin = (WindowPtr)p0;
|
|
Bool* pBool = (Bool*)p2;
|
|
CursorPtr pCursor = wCursor(pWin);
|
|
ScreenPtr pScreen = pWin -> drawable.pScreen;
|
|
|
|
if ((pCursor = wCursor(pWin)) &&
|
|
nxagentCursorPriv(pCursor, pScreen) &&
|
|
nxagentCursor(pCursor, pScreen))
|
|
{
|
|
#ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
|
|
char msg[] = "nxagentDisconnectWindow:";
|
|
|
|
nxagentPrintCursorInfo(pCursor, msg);
|
|
#endif
|
|
|
|
#ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
|
|
fprintf(stderr, "nxagentDisconnectWindow: window %p - disconnecting cursor %p ID %lx\n",
|
|
pWin, pCursor, nxagentCursor(pCursor, pScreen));
|
|
#endif
|
|
|
|
nxagentDisconnectCursor(pCursor, (XID)0, pBool);
|
|
|
|
if (!*pBool)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentDisconnectWindow: WARNING failed disconnection of cursor at [%p]"
|
|
" for window at [%p]: ignoring it.\n", (void*)pCursor, (void*)pWin);
|
|
#endif
|
|
|
|
*pBool = True;
|
|
}
|
|
}
|
|
#ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
|
|
else if (pCursor)
|
|
{
|
|
fprintf(stderr, "nxagentDisconnectWindow: window %p - cursor %p already disconnected\n",
|
|
pWin, pCursor);
|
|
}
|
|
#endif
|
|
|
|
if ((nxagentRealWindowProp) && (!nxagentWindowTopLevel(pWin)))
|
|
{
|
|
Atom prop = MakeAtom("NX_REAL_WINDOW", strlen("NX_REAL_WINDOW"), True);
|
|
|
|
if (DeleteProperty(pWin, prop) != Success)
|
|
{
|
|
fprintf(stderr, "nxagentDisconnectWindow: Deleting NX_REAL_WINDOW failed.\n");
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
fprintf(stderr, "nxagentDisconnectWindow: Deleting NX_REAL_WINDOW from Window ID [%x].\n", nxagentWindowPriv(pWin)->window);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
nxagentWindow(pWin) = None;
|
|
|
|
if (nxagentDrawableStatus((DrawablePtr) pWin) == NotSynchronized)
|
|
{
|
|
nxagentDestroyCorruptedResource((DrawablePtr) pWin, RT_NX_CORR_WINDOW);
|
|
}
|
|
}
|
|
|
|
Bool nxagentReconnectAllWindows(void *p0)
|
|
{
|
|
/*
|
|
access the parameter like this if this function needs it in future:
|
|
int flexibility = *(int *) p0;
|
|
*/
|
|
|
|
#if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_WINDOW_DEBUG)
|
|
fprintf(stderr, "nxagentReconnectAllWindows\n");
|
|
#endif
|
|
|
|
if (screenInfo.screens[0]->root -> backgroundState == BackgroundPixmap &&
|
|
screenInfo.screens[0]->root -> background.pixmap == NULL)
|
|
{
|
|
FatalError("nxagentReconnectAllWindows: correct the FIXME\n");
|
|
}
|
|
|
|
if (nxagentOption(Fullscreen))
|
|
{
|
|
screenInfo.screens[0]->root -> origin.x = nxagentOption(RootX);
|
|
screenInfo.screens[0]->root -> origin.y = nxagentOption(RootY);
|
|
}
|
|
|
|
if (!nxagentLoopOverWindows(nxagentReconnectWindow))
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentReconnectAllWindows: couldn't recreate windows\n");
|
|
#endif
|
|
|
|
return False;
|
|
}
|
|
|
|
#ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
fprintf(stderr, "nxagentReconnectAllWindows: all windows recreated\n");
|
|
#endif
|
|
|
|
if (!nxagentLoopOverWindows(nxagentReconfigureWindow))
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentReconnectAllWindows: couldn't reconfigure windows\n");
|
|
#endif
|
|
|
|
return False;
|
|
}
|
|
|
|
/*
|
|
* After the Root Window has been mapped, the Input Windows is
|
|
* raised.
|
|
*/
|
|
|
|
if (!nxagentOption(Rootless))
|
|
{
|
|
for (int i = 0; i < screenInfo.numScreens; i++)
|
|
{
|
|
XRaiseWindow(nxagentDisplay, nxagentInputWindows[i]);
|
|
}
|
|
}
|
|
|
|
nxagentFlushConfigureWindow();
|
|
|
|
if (nxagentOption(Fullscreen))
|
|
{
|
|
screenInfo.screens[0]->root -> origin.x = 0;
|
|
screenInfo.screens[0]->root -> origin.y = 0;
|
|
}
|
|
|
|
#ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
fprintf(stderr, "nxagentReconnectAllWindows: All windows reconfigured.\n");
|
|
#endif
|
|
|
|
if (!nxagentInitClipboard(screenInfo.screens[0]->root))
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentReconnectAllWindows: WARNING! Couldn't initialize the clipboard.\n");
|
|
#endif
|
|
|
|
return False;
|
|
}
|
|
|
|
#ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
|
|
XSync(nxagentDisplay, 0);
|
|
fprintf(stderr, "nxagentReconnectAllWindows: Clipboard initialized.\n");
|
|
#endif
|
|
|
|
#ifdef VIEWPORT_FRAME
|
|
/*
|
|
* We move the viewport frames out of the way on the X server side.
|
|
*/
|
|
|
|
if (nxagentViewportFrameLeft &&
|
|
nxagentViewportFrameRight &&
|
|
nxagentViewportFrameAbove &&
|
|
nxagentViewportFrameBelow)
|
|
{
|
|
XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameLeft),
|
|
-NXAGENT_FRAME_WIDTH, 0);
|
|
XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameRight),
|
|
nxagentOption(RootWidth), 0);
|
|
XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameAbove),
|
|
0, -NXAGENT_FRAME_WIDTH);
|
|
XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameBelow),
|
|
0, nxagentOption(RootHeight));
|
|
}
|
|
#endif /* #ifdef VIEWPORT_FRAME */
|
|
|
|
return True;
|
|
}
|
|
|
|
Bool nxagentSetWindowCursors(void *p0)
|
|
{
|
|
/*
|
|
access the parameter like this if this function needs it in future:
|
|
int flexibility = *(int *) p0;
|
|
*/
|
|
|
|
#if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_WINDOW_DEBUG)
|
|
fprintf(stderr, "nxagentSetWindowCursors: Going to loop over the windows.\n");
|
|
#endif
|
|
|
|
if (!nxagentLoopOverWindows(nxagentReconfigureWindowCursor))
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentSetWindowCursors: WARNING! Couldn't configure all windows' cursors.\n");
|
|
#endif
|
|
|
|
return False;
|
|
}
|
|
|
|
#ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
|
|
fprintf(stderr, "nxagentSetWindowCursors: All cursors configured.\n");
|
|
#endif
|
|
|
|
nxagentReDisplayCurrentCursor();
|
|
|
|
return True;
|
|
}
|
|
|
|
static void nxagentTraverseWindow(
|
|
WindowPtr pWin,
|
|
void (*pF)(void *, XID, void *),
|
|
void * p)
|
|
{
|
|
pF(pWin, 0, p);
|
|
|
|
if (pWin -> nextSib)
|
|
{
|
|
nxagentTraverseWindow(pWin -> nextSib, pF, p);
|
|
}
|
|
|
|
if (pWin -> firstChild)
|
|
{
|
|
nxagentTraverseWindow(pWin -> firstChild, pF, p);
|
|
}
|
|
}
|
|
|
|
static Bool nxagentLoopOverWindows(void (*pF)(void *, XID, void *))
|
|
{
|
|
Bool windowSuccess = True;
|
|
|
|
for (int i = 0; i < screenInfo.numScreens; i++)
|
|
{
|
|
nxagentTraverseWindow(screenInfo.screens[i]->root, pF, &windowSuccess);
|
|
}
|
|
|
|
return windowSuccess;
|
|
}
|
|
|
|
static void nxagentReconnectWindow(void * param0, XID param1, void * data_buffer)
|
|
{
|
|
WindowPtr pWin = (WindowPtr)param0;
|
|
Bool *pBool = (Bool*)data_buffer;
|
|
Visual *visual;
|
|
unsigned long mask;
|
|
XSetWindowAttributes attributes;
|
|
ColormapPtr pCmap;
|
|
|
|
if (!pWin || !*pBool)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
|
|
fprintf(stderr, "nxagentReconnectWindow: %p - ID %lx\n", pWin, nxagentWindow(pWin));
|
|
#endif
|
|
|
|
if (pWin->drawable.class == InputOnly)
|
|
{
|
|
mask = CWEventMask;
|
|
visual = CopyFromParent;
|
|
}
|
|
else
|
|
{
|
|
mask = CWEventMask | CWBackingStore;
|
|
|
|
attributes.backing_store = NotUseful;
|
|
|
|
if (pWin->optional)
|
|
{
|
|
mask |= CWBackingPlanes | CWBackingPixel;
|
|
attributes.backing_planes = pWin->optional->backingBitPlanes;
|
|
attributes.backing_pixel = pWin->optional->backingPixel;
|
|
}
|
|
|
|
/*
|
|
FIXME: Do we need to set save unders attribute here?
|
|
*/
|
|
if (nxagentSaveUnder)
|
|
{
|
|
mask |= CWSaveUnder;
|
|
attributes.save_under = pWin->saveUnder;
|
|
}
|
|
|
|
if (pWin->parent)
|
|
{
|
|
if (pWin->optional && pWin->optional->visual != wVisual(pWin->parent))
|
|
{
|
|
visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
|
|
mask |= CWColormap;
|
|
if (pWin->optional->colormap)
|
|
{
|
|
pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP);
|
|
attributes.colormap = nxagentColormap(pCmap);
|
|
}
|
|
else
|
|
{
|
|
attributes.colormap = nxagentDefaultVisualColormap(visual);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
visual = CopyFromParent;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* root windows have their own colormaps at creation time */
|
|
visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
|
|
pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP);
|
|
mask |= CWColormap;
|
|
attributes.colormap = nxagentColormap(pCmap);
|
|
}
|
|
}
|
|
|
|
if (mask & CWEventMask)
|
|
{
|
|
attributes.event_mask = nxagentGetEventMask(pWin);
|
|
}
|
|
#ifdef WARNING
|
|
else
|
|
{
|
|
attributes.event_mask = NoEventMask;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentReconnectWindow: Going to create new window.\n");
|
|
fprintf(stderr, "nxagentReconnectWindow: Recreating %swindow at %p current event mask = %lX mask & CWEventMask = %ld "
|
|
"event_mask = %lX\n",
|
|
nxagentWindowTopLevel(pWin) ? "toplevel " : "", (void*)pWin, pWin -> eventMask,
|
|
mask & CWEventMask, attributes.event_mask);
|
|
#endif
|
|
|
|
/*
|
|
* FIXME: This quick hack is intended to solve a problem of NXWin X
|
|
* server for windows. The NXWin minimize the windows moving
|
|
* them out of the screen area, this behaviour can cause
|
|
* problem when a rootless session is disconnected and an
|
|
* apps is minimized. It will be solved with new Xorg
|
|
* version of the NXWin server.
|
|
*/
|
|
|
|
if (nxagentOption(Rootless))
|
|
{
|
|
if (pWin -> drawable.x == -32000 && pWin -> drawable.y == -32000)
|
|
{
|
|
pWin -> drawable.x = (pWin -> drawable.pScreen -> width - pWin -> drawable.width) / 2;
|
|
pWin -> drawable.y = (pWin -> drawable.pScreen -> height - pWin -> drawable.height) /2;
|
|
}
|
|
|
|
if (pWin -> origin.x == -32000 && pWin -> origin.y == -32000)
|
|
{
|
|
pWin -> origin.x = (pWin -> drawable.pScreen -> width - pWin -> drawable.width) / 2;
|
|
pWin -> origin.y = (pWin -> drawable.pScreen -> height - pWin -> drawable.height) / 2;
|
|
}
|
|
}
|
|
|
|
nxagentWindow(pWin) = XCreateWindow(nxagentDisplay,
|
|
nxagentWindowParent(pWin),
|
|
pWin->origin.x -
|
|
wBorderWidth(pWin),
|
|
pWin->origin.y -
|
|
wBorderWidth(pWin),
|
|
pWin->drawable.width,
|
|
pWin->drawable.height,
|
|
pWin->borderWidth,
|
|
pWin->drawable.depth,
|
|
pWin->drawable.class,
|
|
visual,
|
|
mask,
|
|
&attributes);
|
|
|
|
if (nxagentReportPrivateWindowIds)
|
|
{
|
|
fprintf(stderr, "NXAGENT_WINDOW_ID: %s_WINDOW,WID:[0x%x],INT:[0x%x]\n",
|
|
(pWin->drawable.id == pWin->drawable.pScreen->root->drawable.id) ? "ROOT" : "PRIVATE",
|
|
nxagentWindowPriv(pWin)->window, pWin->drawable.id);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
{
|
|
char *winname = NULL;
|
|
|
|
if (-1 != asprintf(&winname, "%s %s[0x%lx]", nxagentWindowName,
|
|
(pWin->drawable.id == pWin->drawable.pScreen->root->drawable.id) ? "Root" : "Private",
|
|
pWin->drawable.id))
|
|
{
|
|
Xutf8SetWMProperties(nxagentDisplay, nxagentWindowPriv(pWin)->window,
|
|
winname, winname, NULL , 0 , NULL, NULL, NULL);
|
|
SAFE_free(winname);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentReconnectWindow: Created new window with id [0x%x].\n",
|
|
nxagentWindowPriv(pWin)->window);
|
|
#endif
|
|
|
|
/*
|
|
* We have to set the WM_DELETE_WINDOW protocols on every top level
|
|
* window, because we don't know if a client handles this.
|
|
*/
|
|
|
|
if (nxagentOption(Rootless) && (pWin != screenInfo.screens[0]->root))
|
|
{
|
|
if (nxagentWindowTopLevel(pWin))
|
|
{
|
|
XlibAtom prop = nxagentMakeAtom("WM_PROTOCOLS", strlen("WM_PROTOCOLS"), True);
|
|
XlibAtom atom = nxagentMakeAtom("WM_DELETE_WINDOW", strlen("WM_DELETE_WINDOW"), True);
|
|
|
|
XSetWMProtocols(nxagentDisplay, nxagentWindow(pWin), &atom, 1);
|
|
|
|
nxagentAddPropertyToList(prop, pWin);
|
|
}
|
|
|
|
nxagentExportAllProperty(pWin);
|
|
|
|
if (nxagentWindowTopLevel(pWin))
|
|
{
|
|
Atom type;
|
|
int format;
|
|
unsigned long nItems, bytesLeft;
|
|
XSizeHints hints = {0};
|
|
unsigned char *data = NULL;
|
|
#ifdef _XSERVER64
|
|
unsigned char *data64 = NULL;
|
|
#endif
|
|
|
|
int ret = GetWindowProperty(pWin,
|
|
XA_WM_NORMAL_HINTS,
|
|
0, sizeof(XSizeHints),
|
|
False, XA_WM_SIZE_HINTS,
|
|
&type, &format, &nItems, &bytesLeft, &data);
|
|
|
|
/*
|
|
* 72 is the number of bytes returned by sizeof(XSizeHints) on
|
|
* 32 bit platforms.
|
|
*/
|
|
|
|
if (ret == Success &&
|
|
((format >> 3) * nItems) == 72 &&
|
|
bytesLeft == 0 &&
|
|
type == XA_WM_SIZE_HINTS)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentReconnectWindow: setting WMSizeHints on window %p [%lx - %lx].\n",
|
|
(void*)pWin, pWin -> drawable.id, nxagentWindow(pWin));
|
|
#endif
|
|
|
|
/* FIXME: use XAllocSizeHints() */
|
|
/* FIXME: all this copying is only done because the first
|
|
element of the XSizeHints struct is a long which is of
|
|
different size on 32bit vs. 64bit platforms. We should
|
|
rewrite this to better readable and probably more robust
|
|
code */
|
|
#ifdef _XSERVER64
|
|
data64 = (unsigned char *) malloc(sizeof(XSizeHints) + 4);
|
|
if (data64)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
*(data64 + i) = *(data + i);
|
|
}
|
|
|
|
*(((int *) data64) + 1) = 0;
|
|
|
|
for (int i = 8; i < sizeof(XSizeHints) + 4; i++)
|
|
{
|
|
*(data64 + i) = *(data + i - 4);
|
|
}
|
|
|
|
XSizeHints *props = (XSizeHints *) data64;
|
|
hints = *props;
|
|
}
|
|
else
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "%s: Failed to alloc memory for XSizeHints\n", __func__);
|
|
#endif
|
|
}
|
|
#else
|
|
XSizeHints *props = (XSizeHints *) data;
|
|
hints = *props;
|
|
#endif /* _XSERVER64 */
|
|
}
|
|
else
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentReconnectWindow: Failed to get property WM_NORMAL_HINTS on window %p\n",
|
|
(void*)pWin);
|
|
#endif
|
|
}
|
|
|
|
hints.flags |= (USPosition | PWinGravity);
|
|
hints.x = pWin -> drawable.x;
|
|
hints.y = pWin -> drawable.y;
|
|
hints.win_gravity = StaticGravity;
|
|
|
|
XSetWMNormalHints(nxagentDisplay,
|
|
nxagentWindow(pWin),
|
|
&hints);
|
|
|
|
#ifdef _XSERVER64
|
|
SAFE_free(data64);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if ((nxagentRealWindowProp) && (!nxagentWindowTopLevel(pWin)))
|
|
{
|
|
Atom prop = MakeAtom("NX_REAL_WINDOW", strlen("NX_REAL_WINDOW"), True);
|
|
|
|
if (ChangeWindowProperty(pWin, prop, XA_WINDOW, 32, PropModeReplace, 1, nxagentWindowPriv(pWin), 1) != Success)
|
|
{
|
|
fprintf(stderr, "nxagentReconnectWindow: Updating NX_REAL_WINDOW failed.\n");
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
fprintf(stderr, "nxagentReconnectWindow: Updated NX_REAL_WINDOW for Window ID [%x].\n", nxagentWindowPriv(pWin)->window);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (nxagentDrawableStatus((DrawablePtr) pWin) == NotSynchronized)
|
|
{
|
|
nxagentAllocateCorruptedResource((DrawablePtr) pWin, RT_NX_CORR_WINDOW);
|
|
}
|
|
}
|
|
|
|
static void nxagentReconfigureWindowCursor(void * param0, XID param1, void * data_buffer)
|
|
{
|
|
WindowPtr pWin = (WindowPtr)param0;
|
|
Bool *pBool = (Bool*)data_buffer;
|
|
CursorPtr pCursor;
|
|
|
|
if (!pWin || !*pBool || !(pCursor = wCursor(pWin)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
ScreenPtr pScreen = pWin -> drawable.pScreen;
|
|
|
|
if (!(nxagentCursorPriv(pCursor, pScreen)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentReconfigureWindowCursor: %p - ID %lx geometry (%d,%d,%d,%d) "
|
|
"cursor %p - ID %lx\n",
|
|
pWin, nxagentWindow(pWin),
|
|
pWin -> drawable.x,
|
|
pWin -> drawable.y,
|
|
pWin -> drawable.width,
|
|
pWin -> drawable.height,
|
|
pCursor, nxagentCursor(pCursor, pScreen));
|
|
#endif
|
|
|
|
if (nxagentCursor(pCursor, pScreen) == None)
|
|
{
|
|
#ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
|
|
fprintf(stderr, "nxagentReconfigureWindowCursor: reconnecting valid cursor %lx\n",
|
|
(void*)pCursor);
|
|
#endif
|
|
|
|
nxagentReconnectCursor(pCursor, 0, pBool);
|
|
|
|
if (!*pBool)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentReconfigureWindowCursor: WARNING "
|
|
"failed reconnection of cursor at [%p] for window at [%p]: ignoring it.\n",
|
|
(void*)pCursor, (void*)pWin);
|
|
#endif
|
|
|
|
*pBool = True;
|
|
}
|
|
}
|
|
|
|
if (nxagentOption(Rootless))
|
|
{
|
|
XDefineCursor(nxagentDisplay,nxagentWindow(pWin),nxagentCursor(pCursor,pScreen));
|
|
}
|
|
}
|
|
|
|
static void nxagentReconfigureWindow(void * param0, XID param1, void * data_buffer)
|
|
{
|
|
WindowPtr pWin = (WindowPtr)param0;
|
|
unsigned long mask = 0;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentReconfigureWindow: pWin %p - ID %lx\n", pWin, nxagentWindow(pWin));
|
|
#endif
|
|
|
|
if (pWin -> drawable.class == InputOnly)
|
|
{
|
|
mask = CWWinGravity | CWEventMask | CWDontPropagate | CWOverrideRedirect | CWCursor;
|
|
}
|
|
else
|
|
{
|
|
mask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBorderPixel |
|
|
CWBitGravity | CWWinGravity | CWBackingStore | CWBackingPlanes |
|
|
CWBackingPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask |
|
|
CWDontPropagate | CWColormap | CWCursor;
|
|
}
|
|
nxagentChangeWindowAttributes(pWin, mask);
|
|
|
|
#ifdef SHAPE
|
|
if (nxagentWindowPriv(pWin) -> boundingShape)
|
|
{
|
|
RegionDestroy(nxagentWindowPriv(pWin) -> boundingShape);
|
|
nxagentWindowPriv(pWin) -> boundingShape = NULL;
|
|
}
|
|
|
|
if (nxagentWindowPriv(pWin) -> clipShape)
|
|
{
|
|
RegionDestroy(nxagentWindowPriv(pWin) -> clipShape);
|
|
nxagentWindowPriv(pWin) -> clipShape = NULL;
|
|
}
|
|
nxagentShapeWindow(pWin);
|
|
#endif
|
|
|
|
if (pWin != screenInfo.screens[0]->root)
|
|
{
|
|
if (pWin->realized)
|
|
{
|
|
nxagentRealizeWindow (pWin);
|
|
}
|
|
/*
|
|
XXX: This would break Motif menus.
|
|
If pWin is mapped but not realized, a following UnmapWindow() wouldn't
|
|
do anything, leaving this mapped window around. XMapWindow()
|
|
is called in nxagentRealizeWindow() and there it is enough.
|
|
|
|
else if (pWin->mapped)
|
|
{
|
|
XMapWindow(nxagentDisplay, nxagentWindow(pWin));
|
|
}
|
|
*/
|
|
else if (nxagentOption(Rootless) && pWin -> overrideRedirect == 0 &&
|
|
nxagentWindowTopLevel(pWin) && nxagentIsIconic(pWin))
|
|
{
|
|
MapWindow(pWin, serverClient);
|
|
XIconifyWindow(nxagentDisplay, nxagentWindow(pWin), pWin -> drawable.pScreen -> myNum);
|
|
}
|
|
}
|
|
else if (!nxagentOption(Rootless))
|
|
{
|
|
/*
|
|
* Map the root window.
|
|
*/
|
|
|
|
XMoveWindow(nxagentDisplay, nxagentWindow(pWin),
|
|
nxagentOption(RootX), nxagentOption(RootY));
|
|
XMapWindow(nxagentDisplay, nxagentWindow(pWin));
|
|
}
|
|
}
|
|
|
|
Bool nxagentCheckIllegalRootMonitoring(WindowPtr pWin, Mask mask)
|
|
{
|
|
Mask invalidMask = SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask;
|
|
|
|
if (nxagentOption(Rootless) &&
|
|
pWin == screenInfo.screens[0]->root &&
|
|
(mask & invalidMask))
|
|
{
|
|
return True;
|
|
}
|
|
|
|
return False;
|
|
}
|
|
|
|
#ifdef TEST
|
|
Bool nxagentCheckWindowIntegrity(WindowPtr pWin)
|
|
{
|
|
Bool integrity = True;
|
|
|
|
unsigned int width = pWin -> drawable.width;
|
|
unsigned int height = pWin -> drawable.height;
|
|
unsigned int depth = pWin -> drawable.depth;
|
|
int format = (depth == 1) ? XYPixmap : ZPixmap;
|
|
|
|
if (width && height)
|
|
{
|
|
unsigned int length = nxagentImageLength(width, height, format, 0, depth);
|
|
char *data = calloc(1, length);
|
|
if (data == NULL)
|
|
{
|
|
FatalError("nxagentCheckWindowIntegrity: Failed to allocate a buffer of size %d.\n", length);
|
|
}
|
|
|
|
unsigned long plane_mask = AllPlanes;
|
|
XImage *image = XGetImage(nxagentDisplay, nxagentWindow(pWin), 0, 0,
|
|
width, height, plane_mask, format);
|
|
if (image == NULL)
|
|
{
|
|
fprintf(stderr, "XGetImage: Failed.\n");
|
|
return False;
|
|
}
|
|
|
|
fbGetImage((DrawablePtr)pWin, 0, 0, width, height, format, plane_mask, data);
|
|
|
|
if (image && memcmp(image->data, data, length) != 0)
|
|
{
|
|
integrity = False;
|
|
|
|
#ifdef TEST
|
|
char *p = image->data, *q = data;
|
|
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
if (p[i] != q[i])
|
|
{
|
|
fprintf(stderr, "[%d] %d - %d !!!!!!!!!!!!!!!!!!! **************** !!!!!!!!!!!!!!!!!\n", i, p[i], q[i]);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "[%d] %d - %d\n", i, p[i], q[i]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentCheckWindowIntegrity: Window %p width %d, height %d, has been realized "
|
|
"but the data buffer still differs.\n", (void*) pWin, width, height);
|
|
fprintf(stderr, "nxagentCheckWindowIntegrity: bytes_per_line = %d byte pad %d format %d.\n",
|
|
image -> bytes_per_line, nxagentImagePad(width, height, 0, depth), image->format);
|
|
|
|
fprintf(stderr, "nxagentCheckWindowIntegrity: image is corrupted!!\n");
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentCheckWindowIntegrity: Window %p has been realized "
|
|
"now remote and framebuffer data are synchronized.\n", (void*) pWin);
|
|
#endif
|
|
}
|
|
|
|
if (image)
|
|
{
|
|
XDestroyImage(image);
|
|
}
|
|
|
|
SAFE_free(data);
|
|
}
|
|
else
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentCheckWindowIntegrity: ignored window %p with geometry (%d,%d).\n",
|
|
(void*) pWin, width, height);
|
|
#endif
|
|
}
|
|
|
|
return integrity;
|
|
}
|
|
#endif /* TEST */
|
|
|
|
Bool nxagentIsIconic(WindowPtr pWin)
|
|
{
|
|
unsigned long ulReturnItems;
|
|
unsigned long ulReturnBytesLeft;
|
|
Atom atomReturnType;
|
|
int iReturnFormat;
|
|
unsigned char *pszReturnData = NULL;
|
|
|
|
if (!wUserProps (pWin))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int iReturn = GetWindowProperty(pWin, MakeAtom("WM_STATE", 8, False), 0, sizeof(CARD32), False,
|
|
AnyPropertyType, &atomReturnType, &iReturnFormat,
|
|
&ulReturnItems, &ulReturnBytesLeft, &pszReturnData);
|
|
|
|
if (iReturn == Success)
|
|
{
|
|
return (((CARD32 *)pszReturnData)[0] == IconicState);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* pass Eventmask to the real X server (for the rootless toplevel window only) */
|
|
void nxagentSetTopLevelEventMask(WindowPtr pWin)
|
|
{
|
|
if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin))
|
|
{
|
|
XSetWindowAttributes attributes = {.event_mask = nxagentGetEventMask(pWin)};
|
|
XChangeWindowAttributes(nxagentDisplay, nxagentWindow(pWin), CWEventMask, &attributes);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Run nxagentConfigureWindow() on all windows in
|
|
* nxagentConfiguredWindowList and move them from the list
|
|
* afterwards. The list will be empty then.
|
|
*
|
|
* This is also taking care of entries in nxagentExposeQueue that need
|
|
* to be synchronized with the real X server.
|
|
*/
|
|
void nxagentFlushConfigureWindow(void)
|
|
{
|
|
ConfiguredWindowStruct *index = nxagentConfiguredWindowList;
|
|
|
|
while (index)
|
|
{
|
|
if (index -> next == NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
index = index -> next;
|
|
}
|
|
|
|
while (index)
|
|
{
|
|
WindowPtr pWin = index -> pWin;
|
|
unsigned int valuemask = index -> valuemask;
|
|
|
|
if (pWin && valuemask)
|
|
{
|
|
nxagentConfigureWindow(pWin, valuemask);
|
|
}
|
|
|
|
if (index == nxagentConfiguredWindowList)
|
|
{
|
|
SAFE_free(index);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
ConfiguredWindowStruct *tmp = index;
|
|
index = index -> prev;
|
|
SAFE_free(tmp);
|
|
}
|
|
}
|
|
|
|
nxagentConfiguredWindowList = NULL;
|
|
|
|
for (int j = 0; j < nxagentExposeQueue.length; j++)
|
|
{
|
|
int i = (nxagentExposeQueue.start + j) % EXPOSED_SIZE;
|
|
|
|
if (nxagentExposeQueue.exposures[i].synchronize == 1)
|
|
{
|
|
XWindowChanges changes = {
|
|
.x = nxagentExposeQueue.exposures[i].serial,
|
|
.y = -2
|
|
};
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentFlushConfigureWindow: Sending synch ConfigureWindow for "
|
|
"index [%d] serial [%d].\n", i, nxagentExposeQueue.exposures[i].serial);
|
|
#endif
|
|
|
|
XConfigureWindow(nxagentDisplay, nxagentConfiguredSynchroWindow,
|
|
CWX | CWY, &changes);
|
|
|
|
nxagentExposeQueue.exposures[i].synchronize = 0;
|
|
}
|
|
}
|
|
|
|
nxagentSendDeferredBackgroundExposures();
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* from "Definition of the Porting Layer for X v11 Sample Server":
|
|
*
|
|
* If this routine is not NULL, DIX calls it shortly after calling
|
|
* ValidateTree, passing it the same arguments. This is useful for
|
|
* managing multi-layered framebuffers. The sample server sets this to
|
|
* NULL.
|
|
*/
|
|
void nxagentPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
|
|
{
|
|
/*
|
|
FIXME: Do we need this here?
|
|
|
|
nxagentFlushConfigureWindow();
|
|
*/
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Add the given window to the beginning of
|
|
* nxagentconfiguredWindowList. This list collects all windows that
|
|
* need to be reconfigured on the real X server. valuemask defines
|
|
* what changes need to be done. The required values (like position,
|
|
* size, ...) are already stored in pWin).
|
|
*
|
|
* Note that we just add the window to the list here. The actual work
|
|
* will be done by nxagentFlushConfigureWindow() later.
|
|
*/
|
|
void nxagentAddConfiguredWindow(WindowPtr pWin, unsigned int valuemask)
|
|
{
|
|
unsigned int mask;
|
|
|
|
mask = valuemask & (CWSibling | CWX | CWY | CWWidth | CWHeight |
|
|
CWBorderWidth | CWStackMode | CW_Map | CW_Update | CW_Shape);
|
|
|
|
valuemask &= ~(CWSibling | CWX | CWY | CWWidth | CWHeight | CWBorderWidth | CWStackMode);
|
|
|
|
if (mask & CWX &&
|
|
nxagentWindowPriv(pWin)->x !=
|
|
pWin->origin.x - wBorderWidth(pWin))
|
|
{
|
|
valuemask |= CWX;
|
|
}
|
|
|
|
if (mask & CWY &&
|
|
nxagentWindowPriv(pWin)->y !=
|
|
pWin->origin.y - wBorderWidth(pWin))
|
|
{
|
|
valuemask |= CWY;
|
|
}
|
|
|
|
if (mask & CWWidth &&
|
|
nxagentWindowPriv(pWin)->width !=
|
|
pWin->drawable.width)
|
|
{
|
|
valuemask |= CWWidth;
|
|
}
|
|
|
|
if (mask & CWHeight &&
|
|
nxagentWindowPriv(pWin)->height !=
|
|
pWin->drawable.height)
|
|
{
|
|
valuemask |= CWHeight;
|
|
}
|
|
|
|
if (mask & CWBorderWidth &&
|
|
nxagentWindowPriv(pWin)->borderWidth !=
|
|
pWin->borderWidth)
|
|
{
|
|
valuemask |= CWBorderWidth;
|
|
}
|
|
|
|
if (mask & CWStackMode &&
|
|
nxagentWindowPriv(pWin)->siblingAbove !=
|
|
nxagentWindowSiblingAbove(pWin))
|
|
{
|
|
valuemask |= CWStackMode;
|
|
}
|
|
|
|
{
|
|
ConfiguredWindowStruct *tmp = nxagentConfiguredWindowList;
|
|
|
|
nxagentConfiguredWindowList = malloc(sizeof(ConfiguredWindowStruct));
|
|
nxagentConfiguredWindowList -> next = tmp; /* can be NULL */
|
|
nxagentConfiguredWindowList -> prev = NULL;
|
|
nxagentConfiguredWindowList -> pWin = pWin;
|
|
nxagentConfiguredWindowList -> valuemask = valuemask;
|
|
|
|
if (tmp)
|
|
{
|
|
tmp -> prev = nxagentConfiguredWindowList;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* remove pWin from nxgentConfigureWindowList
|
|
*
|
|
* This is just updating the linked list and freeing the
|
|
* given entry. It will not perform any X stuff
|
|
*/
|
|
void nxagentDeleteConfiguredWindow(WindowPtr pWin)
|
|
{
|
|
ConfiguredWindowStruct *index, *previous, *tmp;
|
|
|
|
index = nxagentConfiguredWindowList;
|
|
|
|
while (index)
|
|
{
|
|
WindowPtr pDel = index -> pWin;
|
|
|
|
if (pDel == pWin)
|
|
{
|
|
if (index -> prev == NULL && index -> next == NULL)
|
|
{
|
|
SAFE_free(nxagentConfiguredWindowList);
|
|
return;
|
|
}
|
|
else if (index -> prev == NULL)
|
|
{
|
|
tmp = nxagentConfiguredWindowList;
|
|
index = nxagentConfiguredWindowList = tmp -> next;
|
|
SAFE_free(tmp);
|
|
nxagentConfiguredWindowList -> prev = NULL;
|
|
|
|
continue;
|
|
}
|
|
else if (index -> next == NULL)
|
|
{
|
|
tmp = index;
|
|
index = index -> prev;
|
|
SAFE_free(tmp);
|
|
index -> next = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
previous = index -> prev;
|
|
tmp = index;
|
|
index = index -> next;
|
|
previous -> next = index;
|
|
index -> prev = previous;
|
|
SAFE_free(tmp);
|
|
|
|
continue;
|
|
}
|
|
|
|
index = index -> next;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void nxagentAddStaticResizedWindow(WindowPtr pWin, unsigned long sequence, int offX, int offY)
|
|
{
|
|
StaticResizedWindowStruct *tmp = nxagentStaticResizedWindowList;
|
|
|
|
nxagentStaticResizedWindowList = malloc(sizeof(StaticResizedWindowStruct));
|
|
if (!nxagentStaticResizedWindowList)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "WARNING: could not allocate memory for nxagentStaticResizedWindowList\n");
|
|
#endif
|
|
nxagentStaticResizedWindowList = tmp;
|
|
return;
|
|
}
|
|
nxagentStaticResizedWindowList -> next = tmp;
|
|
nxagentStaticResizedWindowList -> prev = NULL;
|
|
|
|
if (tmp)
|
|
{
|
|
tmp -> prev = nxagentStaticResizedWindowList;
|
|
}
|
|
|
|
nxagentStaticResizedWindowList -> pWin = pWin;
|
|
nxagentStaticResizedWindowList -> sequence = sequence;
|
|
nxagentStaticResizedWindowList -> offX = offX;
|
|
nxagentStaticResizedWindowList -> offY = offY;
|
|
}
|
|
|
|
void nxagentDeleteStaticResizedWindow(unsigned long sequence)
|
|
{
|
|
StaticResizedWindowStruct *index, *previous, *tmp;
|
|
|
|
index = nxagentStaticResizedWindowList;
|
|
|
|
while (index)
|
|
{
|
|
if (index -> sequence <= sequence)
|
|
{
|
|
if (index -> prev == NULL && index -> next == NULL)
|
|
{
|
|
SAFE_free(nxagentStaticResizedWindowList);
|
|
return;
|
|
}
|
|
else if (index -> prev == NULL)
|
|
{
|
|
tmp = nxagentStaticResizedWindowList;
|
|
index = nxagentStaticResizedWindowList = tmp -> next;
|
|
SAFE_free(tmp);
|
|
nxagentStaticResizedWindowList -> prev = NULL;
|
|
|
|
continue;
|
|
}
|
|
else if (index -> next == NULL)
|
|
{
|
|
tmp = index;
|
|
index = index -> prev;
|
|
SAFE_free(tmp);
|
|
index -> next = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
previous = index -> prev;
|
|
tmp = index;
|
|
index = index -> next;
|
|
previous -> next = index;
|
|
index -> prev = previous;
|
|
SAFE_free(tmp);
|
|
|
|
continue;
|
|
}
|
|
|
|
index = index -> next;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
StaticResizedWindowStruct *nxagentFindStaticResizedWindow(unsigned long sequence)
|
|
{
|
|
StaticResizedWindowStruct *ret = NULL;
|
|
|
|
if (nxagentStaticResizedWindowList == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
StaticResizedWindowStruct *index = nxagentStaticResizedWindowList;
|
|
|
|
while (index && index -> sequence > sequence)
|
|
{
|
|
ret = index;
|
|
index = index -> next;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void nxagentEmptyBackingStoreRegion(void * param0, XID param1, void * data_buffer)
|
|
{
|
|
WindowPtr pWin = (WindowPtr) param0;
|
|
|
|
miBSWindowPtr pBackingStore = (miBSWindowPtr)pWin->backStorage;
|
|
|
|
if (pBackingStore != NULL)
|
|
{
|
|
RegionEmpty(&pBackingStore->SavedRegion);
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentEmptyBackingStoreRegion: Emptying saved region for window at [%p].\n", (void*) pWin);
|
|
#endif
|
|
|
|
if (pBackingStore -> pBackingPixmap != NULL)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentEmptyBackingStoreRegion: Emptying corrupted region for drawable at [%p].\n",
|
|
(void*) pBackingStore -> pBackingPixmap);
|
|
#endif
|
|
|
|
nxagentUnmarkCorruptedRegion((DrawablePtr) pBackingStore -> pBackingPixmap, NullRegion);
|
|
}
|
|
}
|
|
}
|
|
|
|
void nxagentEmptyAllBackingStoreRegions(void)
|
|
{
|
|
if (nxagentLoopOverWindows(nxagentEmptyBackingStoreRegion) == 0)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentEmptyAllSavedRegions: Failed to empty backing store saved regions.\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void nxagentInitBSPixmapList(void)
|
|
{
|
|
memset(nxagentBSPixmapList, 0, BSPIXMAPLIMIT * sizeof( StoringPixmapPtr));
|
|
}
|
|
|
|
int nxagentAddItemBSPixmapList(unsigned long id, PixmapPtr pPixmap, WindowPtr pWin, int bsx, int bsy)
|
|
{
|
|
for (int i = 0; i < BSPIXMAPLIMIT; i++)
|
|
{
|
|
if (nxagentBSPixmapList[i] == NULL)
|
|
{
|
|
nxagentBSPixmapList[i] = malloc(sizeof(StoringPixmapRec));
|
|
|
|
if (nxagentBSPixmapList[i] == NULL)
|
|
{
|
|
FatalError("nxagentAddItemBSPixmapList: Failed to allocate memory for nxagentBSPixmapList.\n");
|
|
}
|
|
|
|
nxagentBSPixmapList[i] -> storingPixmapId = id;
|
|
nxagentBSPixmapList[i] -> pStoringPixmap = pPixmap;
|
|
nxagentBSPixmapList[i] -> pSavedWindow = pWin;
|
|
nxagentBSPixmapList[i] -> backingStoreX = bsx;
|
|
nxagentBSPixmapList[i] -> backingStoreY = bsy;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentAddItemBSPixmapList: Added Pixmap with id [%lu] to nxagentBSPixmapList.\n", id);
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
|
|
if (nxagentBSPixmapList[i] -> storingPixmapId == id)
|
|
{
|
|
nxagentBSPixmapList[i] -> pStoringPixmap = pPixmap;
|
|
nxagentBSPixmapList[i] -> pSavedWindow = pWin;
|
|
nxagentBSPixmapList[i] -> backingStoreX = bsx;
|
|
nxagentBSPixmapList[i] -> backingStoreY = bsy;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentAddItemBSPixmapList: Updated existing item for id [%lu].\n", id);
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentAddItemBSPixmapList: WARNING! List item full.\n");
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
int nxagentRemoveItemBSPixmapList(unsigned long pixmapId)
|
|
{
|
|
if (pixmapId == 0 || nxagentBSPixmapList[0] == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
for (int i = 0; i < BSPIXMAPLIMIT; i++)
|
|
{
|
|
if ((nxagentBSPixmapList[i] != NULL) &&
|
|
(nxagentBSPixmapList[i] -> storingPixmapId == pixmapId))
|
|
{
|
|
SAFE_free(nxagentBSPixmapList[i]);
|
|
|
|
if (i < BSPIXMAPLIMIT - 1)
|
|
{
|
|
int j;
|
|
|
|
for (j = i; j < BSPIXMAPLIMIT -1; j++)
|
|
{
|
|
nxagentBSPixmapList[j] = nxagentBSPixmapList[j + 1];
|
|
}
|
|
|
|
if (nxagentBSPixmapList[j] == nxagentBSPixmapList[j - 1])
|
|
{
|
|
nxagentBSPixmapList[j] = NULL;
|
|
}
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentRemoveItemBSPixmapList: Removed Pixmap with id [%lu] from list.\n",
|
|
pixmapId);
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentRemoveItemBSPixmapList: WARNING! Can't remove item [%lu]: item not found.\n",
|
|
pixmapId);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
int nxagentEmptyBSPixmapList(void)
|
|
{
|
|
for (int i = 0; i < BSPIXMAPLIMIT; i++)
|
|
{
|
|
SAFE_free(nxagentBSPixmapList[i]);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
StoringPixmapPtr nxagentFindItemBSPixmapList(unsigned long pixmapId)
|
|
{
|
|
for (int i = 0; i < BSPIXMAPLIMIT; i++)
|
|
{
|
|
if ((nxagentBSPixmapList[i] != NULL) &&
|
|
(nxagentBSPixmapList[i] -> storingPixmapId == pixmapId))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: pixmapId [%lu].\n", __func__, pixmapId);
|
|
fprintf(stderr, "%s: nxagentBSPixmapList[%d] = [%p].\n", __func__,
|
|
i, (void *) nxagentBSPixmapList[i]);
|
|
fprintf(stderr, "%s: nxagentBSPixmapList[%d] -> storingPixmapId [%lu].\n", __func__,
|
|
i, nxagentBSPixmapList[i] -> storingPixmapId);
|
|
#endif
|
|
|
|
return nxagentBSPixmapList[i];
|
|
}
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: WARNING! Item not found.\n", __func__);
|
|
#endif
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "%s: Pixmap with id [%lu] not found.\n", __func__,
|
|
pixmapId);
|
|
#endif
|
|
|
|
return NULL;
|
|
}
|