diff options
Diffstat (limited to 'nx-X11/programs/Xserver/hw/nxagent/Rootless.c')
-rw-r--r-- | nx-X11/programs/Xserver/hw/nxagent/Rootless.c | 1112 |
1 files changed, 1112 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Rootless.c b/nx-X11/programs/Xserver/hw/nxagent/Rootless.c new file mode 100644 index 000000000..cd69af665 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/nxagent/Rootless.c @@ -0,0 +1,1112 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of NoMachine S.r.l. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + +#include "X.h" + +#include "../../include/window.h" +#include "windowstr.h" +#include "colormapst.h" +#include "propertyst.h" + +#include "Agent.h" +#include "Display.h" +#include "Drawable.h" +#include "Windows.h" +#include "Pixmaps.h" +#include "Atoms.h" +#include "Trap.h" + +#include "NXlib.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +/* + * Assigned at the time the root window is + * initialized. + */ + +WindowPtr nxagentRootlessWindow = NULL; + +#define TOP_LEVEL_TABLE_UNIT 100 + +typedef struct { + Window xid; + WindowPtr pWin; +} TopLevelParentRec; + +typedef struct { + TopLevelParentRec *elt; + int next; + int size; +} TopLevelParentMap; + +static TopLevelParentMap topLevelParentMap = { NULL, 0, 0 }; + +static void nxagentRemovePropertyFromList(void); + +/* + * This is currently unused. + */ + +#ifdef TEST + +static void nxagentPrintRootlessTopLevelWindowMap(void); + +void nxagentPrintRootlessTopLevelWindowMap() +{ + int i; + + fprintf(stderr, "nxagentPrintRootlessTopLevelWindowMap: Map size is [%d] num of entry [%d].\n", + topLevelParentMap.size, topLevelParentMap.next); + + for (i = 0; i < topLevelParentMap.next; i++) + { + fprintf(stderr, "nxagentPrintRootlessTopLevelWindowMap: [%d] pWin at [%p] XID at [%ld].\n", + i, (void *) topLevelParentMap.elt[i].pWin, (long int) topLevelParentMap.elt[i].xid); + } +} + +#endif + +void nxagentRootlessAddTopLevelWindow(WindowPtr pWin, Window w) +{ + int i; + + for (i = 0; i < topLevelParentMap.next; i++) + { + if (topLevelParentMap.elt[i].pWin == pWin) + { + #ifdef TEST + fprintf(stderr, "nxagentRootlessAddTopLevelWindow: WARNING! " + "Trying to add duplicated entry window at [%p] xid [%ld].\n", + (void *) pWin, w); + #endif + + topLevelParentMap.elt[i].xid = w; + + return; + } + } + + if (topLevelParentMap.next == topLevelParentMap.size) + { + TopLevelParentRec *ptr = topLevelParentMap.elt; + size_t size = (topLevelParentMap.size += TOP_LEVEL_TABLE_UNIT); + + ptr = realloc(ptr, size * sizeof(TopLevelParentRec)); + + if (ptr == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentRootlessAddTopLevelWindow: Warning failed to allocate memory.\n"); + #endif + + return; + } + + topLevelParentMap.elt = ptr; + topLevelParentMap.size = size; + } + + topLevelParentMap.elt[topLevelParentMap.next].xid = w; + topLevelParentMap.elt[topLevelParentMap.next].pWin = pWin; + topLevelParentMap.next++; +} + +WindowPtr nxagentRootlessTopLevelWindow(Window w) +{ + int i; + + for (i = 0; i < topLevelParentMap.next; i++) + { + if (w == topLevelParentMap.elt[i].xid) + { + return topLevelParentMap.elt[i].pWin; + } + } + + return NULL; +} + +void nxagentRootlessDelTopLevelWindow(WindowPtr pWin) +{ + int i; + + for (i = 0; i < topLevelParentMap.next; i++) + { + if (pWin == topLevelParentMap.elt[i].pWin) + { + topLevelParentMap.elt[i] = topLevelParentMap.elt[topLevelParentMap.next - 1]; + topLevelParentMap.next--; + + return; + } + } +} + +Window nxagentRootlessWMTopLevelWindow(WindowPtr pWin); + +void nxagentConfigureRootlessWindow(WindowPtr pWin, int x, int y, int w, int h, int bw, + WindowPtr pSib, int stack_mode, Mask mask) +{ + XWindowChanges changes; + Window sibw = 0; + + changes.x = x; + changes.y = y; + changes.width = w; + changes.height = h; + changes.border_width = bw; + changes.stack_mode = stack_mode; + + if (pSib) + { + sibw = nxagentWindow(pSib); + } + + if (sibw) + { + changes.sibling = sibw; + } + + XConfigureWindow(nxagentDisplay, nxagentWindow(pWin), mask, &changes); +} + +void nxagentCirculateRootlessWindows(int direction) +{ + XCirculateSubwindows(nxagentDisplay, DefaultRootWindow(nxagentDisplay), direction); +} + +#ifdef DEBUG + +Bool nxagentRootlessTreesMatch() +{ + Window root_return; + Window parent_return; + Window *children_return; + unsigned int nChildrenReturn; + WindowPtr pW; + WindowPtr pTestWin = WindowTable[0] -> firstChild; + Bool treesMatch = True; + Status result; + + result = XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay), + &root_return, &parent_return, &children_return, &nChildrenReturn); + + if (!result) + { + #ifdef WARNING + fprintf(stderr, "nxagentRootlessTreesMatch: WARNING! Failed QueryTree request.\n"); + #endif + + return False; + } + + while (nChildrenReturn > 0) + { + pW = nxagentWindowPtr(children_return[--nChildrenReturn]); + + if (!pW) + { + pW = nxagentRootlessTopLevelWindow(children_return[nChildrenReturn]); + } + + if (pW && pW != WindowTable[0]) + { + if (treesMatch && pTestWin && pTestWin == pW) + { + pTestWin = pTestWin -> nextSib; + } + else + { + treesMatch = False; + } + } + } + + if (children_return) + { + XFree(children_return); + } + + return treesMatch; +} + +#endif + +#ifndef _XSERVER64 +void nxagentRootlessRestack(Window children[], unsigned int nchildren) +#else +void nxagentRootlessRestack(unsigned long children[], unsigned int nchildren) +#endif +{ + WindowPtr *toplevel; + unsigned int ntoplevel; + int i; + WindowPtr pWin; + ClientPtr pClient; + XID values[2]; + Mask mask; + + toplevel = xalloc(sizeof(WindowPtr) * nchildren); + ntoplevel = 0; + + for(i = 0; i < nchildren; i++) + { + pWin = nxagentWindowPtr(children[i]); + + if (!pWin) + { + pWin = nxagentRootlessTopLevelWindow(children[i]); + } + + if (pWin && pWin != WindowTable[0]) + { + toplevel[ntoplevel++] = pWin; + } + } + + if (!ntoplevel) + { + return; + } + + #ifdef DEBUG + + fprintf(stderr, "nxagentRootlessRestack: External top level windows before restack:"); + + for (i = 0; i < ntoplevel; i++) + { + fprintf(stderr, "[%p]\n", toplevel[i]); + } + + fprintf(stderr, "nxagentRootlessRestack: Internal top level windows before restack:"); + + for (pWin = WindowTable[0] -> firstChild; pWin != NULL; pWin = pWin -> nextSib) + { + fprintf(stderr, "[%p]\n", pWin); + } + + #endif + + pWin = WindowTable[0] -> firstChild; + + values[1] = (XID) Above; + + while(ntoplevel-- > 0 && pWin != NULL) + { + if (toplevel[ntoplevel] != pWin) + { + mask = CWSibling | CWStackMode; + values[0] = pWin -> drawable.id; + pClient = wClient(toplevel[ntoplevel]); + nxagentScreenTrap = 1; + ConfigureWindow(toplevel[ntoplevel], mask, (XID *) values, pClient); + nxagentScreenTrap = 0; + + #ifdef TEST + fprintf(stderr, "nxagentRootlessRestack: Restacked window [%p].\n", (void*) toplevel[ntoplevel]); + #endif + } + + pWin = toplevel[ntoplevel] -> nextSib; + } + + #ifdef DEBUG + + fprintf(stderr, "nxagentRootlessRestack: External top level windows after restack:"); + + ntoplevel = i; + + for (i = 0; i < ntoplevel; i++) + { + fprintf(stderr, "[%p]\n", toplevel[i]); + } + + fprintf(stderr, "nxagentRootlessRestack: Internal top level windows after restack:"); + + for (pWin = WindowTable[0] -> firstChild; pWin != NULL; pWin = pWin -> nextSib) + { + fprintf(stderr, "[%p]\n", pWin); + } + + #endif + + xfree(toplevel); + + return; +} + +/* + * Determine if window is a top-level window. + */ + +Window nxagentRootlessWindowParent(WindowPtr pWin) +{ + #ifdef TEST + fprintf(stderr, "nxagentRootlessWindowParent: Called for window at [%p][%ld] with parent [%p][%ld].\n", + (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin->parent, + (pWin->parent ? nxagentWindowPriv(pWin->parent)->window : 0)); + #endif + + if (pWin -> parent == NULL) + { + return DefaultRootWindow(nxagentDisplay); + } + else if (pWin -> parent == nxagentRootlessWindow) + { + return DefaultRootWindow(nxagentDisplay); + } + else + { + return nxagentWindow(pWin -> parent); + } +} + +int nxagentExportAllProperty(pWin) + WindowPtr pWin; +{ + PropertyPtr pProp; + int total = 0; + + for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) + { + total += nxagentExportProperty(pWin, + pProp->propertyName, + pProp->type, + pProp->format, + PropModeReplace, + pProp->size, + pProp->data); + } + + return total; +} + +int nxagentExportProperty(pWin, property, type, format, mode, nUnits, value) + WindowPtr pWin; + Atom property, type; + int format, mode; + unsigned long nUnits; + pointer value; +{ + char *propertyS, *typeS; + Atom propertyX, typeX; + char *output = NULL; + XWMHints wmHints; + Bool export = False; + Bool freeMem = False; + + if (NXDisplayError(nxagentDisplay) == 1) + { + return 0; + } + + propertyS = NameForAtom(property); + typeS = NameForAtom(type); + + if (strncmp(propertyS, "WM_", 3) != 0 && + strncmp(propertyS, "_NET_", 5) != 0 && + strcmp(propertyS, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR") != 0) + { + #ifdef TEST + fprintf(stderr, "nxagentExportProperty: WARNING! Ignored ChangeProperty " + "on %swindow %lx property %s type %s nUnits %ld format %d\n", + nxagentWindowTopLevel(pWin) ? "toplevel " : "", nxagentWindow(pWin), + validateString(propertyS), validateString(typeS), nUnits, format); + #endif + } + else if (strcmp(typeS, "STRING") == 0 || + #ifndef _XSERVER64 + strcmp(typeS, "CARDINAL") == 0 || + strcmp(typeS, "WM_SIZE_HINTS") == 0 || + #endif + strcmp(typeS, "UTF8_STRING") == 0) + { + output = value; + export = True; + } + #ifdef _XSERVER64 + else if (strcmp(typeS, "CARDINAL") == 0 || strcmp(typeS, "WM_SIZE_HINTS") == 0) + { + unsigned long *buffer = malloc(nUnits * sizeof(*buffer)); + int *input = value; + int i; + + if (buffer) + { + freeMem = True; + export = True; + output = (char*) buffer; + + for (i = 0; i < nUnits; i++) + { + buffer[i] = input[i]; + } + } + } + #endif + else if (strcmp(typeS, "WM_HINTS") == 0) + { + ClientPtr pClient = wClient(pWin); + wmHints = *(XWMHints*)value; + + wmHints.flags |= InputHint; + wmHints.input = True; + + output = (char*) &wmHints; + export = True; + + if ((wmHints.flags & IconPixmapHint) && (wmHints.icon_pixmap != None)) + { + PixmapPtr icon = (PixmapPtr)SecurityLookupIDByType(pClient, wmHints.icon_pixmap, + RT_PIXMAP, SecurityDestroyAccess); + + if (icon) + { + if (nxagentDrawableStatus((DrawablePtr) icon) == NotSynchronized) + { + nxagentSynchronizeRegion((DrawablePtr) icon, NullRegion, NEVER_BREAK, NULL); + } + + wmHints.icon_pixmap = nxagentPixmap(icon); + } + else + { + wmHints.flags &= ~IconPixmapHint; + + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon pixmap %lx from hint " + "exporting property %s type %s on window %p.\n", + wmHints.icon_pixmap, propertyS, typeS, (void*)pWin); + #endif + } + } + + if ((wmHints.flags & IconWindowHint) && (wmHints.icon_window != None)) + { + WindowPtr icon = (WindowPtr)SecurityLookupWindow(wmHints.icon_window, pClient, + SecurityDestroyAccess); + + if (icon) + { + wmHints.icon_window = nxagentWindow(icon); + } + else + { + wmHints.flags &= ~IconWindowHint; + + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon window %lx from hint " + "exporting property %s type %s on window %p.\n", + wmHints.icon_window, propertyS, typeS, (void*)pWin); + #endif + } + } + + if ((wmHints.flags & IconMaskHint) && (wmHints.icon_mask != None)) + { + PixmapPtr icon = (PixmapPtr)SecurityLookupIDByType(pClient, wmHints.icon_mask, + RT_PIXMAP, SecurityDestroyAccess); + + if (icon) + { + wmHints.icon_mask = nxagentPixmap(icon); + } + else + { + wmHints.flags &= ~IconMaskHint; + + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon mask %lx from hint " + "exporting property %s type %s on window %p.\n", + wmHints.icon_mask, propertyS, typeS, (void*)pWin); + #endif + } + } + + if ((wmHints.flags & WindowGroupHint) && (wmHints.window_group != None)) + { + WindowPtr window = (WindowPtr)SecurityLookupWindow(wmHints.window_group, pClient, + SecurityDestroyAccess); + + if (window) + { + wmHints.window_group = nxagentWindow(window); + } + else + { + wmHints.flags &= ~WindowGroupHint; + + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up window group %lx from hint " + "exporting property %s type %s on window %p.\n", + wmHints.window_group, propertyS, typeS, (void*)pWin); + #endif + } + } + } + else if (strcmp(typeS, "ATOM") == 0) + { + XlibAtom *atoms = malloc(nUnits * sizeof(*atoms)); + Atom *input = value; + int i; + + freeMem = True; + export = True; + output = (char *) atoms; + + for (i = 0; i < nUnits; i++) + { + atoms[i] = nxagentLocalToRemoteAtom(input[i]); + + if (atoms[i] == None) + { + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to convert local atom %ld [%s].\n", + (long int) input[i], validateString(NameForAtom(input[i]))); + #endif + } + } + } + else if (strcmp(typeS, "WINDOW") == 0) + { + Window *input = value; + XlibWindow *wind = malloc(nUnits * sizeof(*wind)); + ClientPtr pClient = wClient(pWin); + WindowPtr pWindow; + int i; + + freeMem = True; + export = True; + output = (char*) wind; + + for (i = 0; i < nUnits; i++) + { + pWindow = (WindowPtr)SecurityLookupWindow(input[i], pClient, + SecurityDestroyAccess); + if ((input[i] != None) && pWindow) + { + wind[i] = nxagentWindow(pWindow); + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up window %ld " + "exporting property %s type %s on window %p.\n", + (long int) input[i], propertyS, typeS, (void *) pWin); + #endif + + /* + * It seems that clients specifie + * strange windows, perhaps are + * not real windows so we can try + * to let them pass anyway. + * + * wind[i] = None; + * + */ + } + } + } + + if (export) + { + propertyX = nxagentLocalToRemoteAtom(property); + typeX = nxagentLocalToRemoteAtom(type); + + if (propertyX == None || typeX == None) + { + #ifdef WARNING + fprintf(stderr, "nxagentExportProperty: WARNING! Failed to convert local atom.\n"); + #endif + + export = 0; + } + else + { + XChangeProperty(nxagentDisplay, nxagentWindow(pWin), propertyX, typeX, format, mode, (void*)output, nUnits); + nxagentAddPropertyToList(propertyX, pWin); + } + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentExportProperty: WARNING! Ignored ChangeProperty " + "on %swindow %lx property %s type %s nUnits %ld format %d\n", + nxagentWindowTopLevel(pWin) ? "toplevel " : "", + nxagentWindow(pWin), validateString(propertyS), validateString(typeS), + nUnits, format); + #endif + } + + if (freeMem) + { + xfree(output); + } + + return export; +} + +void nxagentImportProperty(Window window, + Atom property, + Atom type, + int format, + unsigned long nitems, + unsigned long bytes_after, + unsigned char *buffer) +{ + Atom propertyL; + Atom typeL; + + WindowPtr pWin; + Bool import = False; + Bool freeMem = False; + XWMHints wmHints; + + typedef struct { + CARD32 state; + Window icon; + } WMState; + WMState wmState; + + char *output = NULL; + char *typeS; + + pWin = nxagentWindowPtr(window); + + if (pWin == NULL) + { + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: Failed to look up remote window %lx property [%ld] exiting.\n", + window, property); + #endif + + return; + } + + propertyL = nxagentRemoteToLocalAtom(property); + + if (!ValidAtom(propertyL)) + { + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: Failed to convert remote property atom.\n"); + #endif + + return; + } + + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: Window %lx property [%ld]: %s\n", + window, property, validateString(NameForAtom(propertyL))); + #endif + + /* + * We settle a property size limit of + * 256K beyond which we simply ignore them. + */ + + typeL = nxagentRemoteToLocalAtom(type); + typeS = NameForAtom(typeL); + + if (buffer == NULL && (nitems > 0)) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: Failed to retrieve remote property [%ld] %s on Window %ld\n", + (long int) property, validateString(NameForAtom(propertyL)), (long int) window); + #endif + } + else if (bytes_after != 0) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: Remote property bigger than maximum limits.\n"); + #endif + } + else if (!ValidAtom(typeL)) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: Failed to convert remote atoms [%ld].\n", + (long int) type); + #endif + } + else if (nitems == 0) + { + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: Importing void property.\n"); + #endif + + import = True; + } + else if (strcmp(typeS, "STRING") == 0 || + strcmp(typeS, "UTF8_STRING") == 0 || + strcmp(typeS, "CARDINAL") == 0 || + strcmp(typeS, "WM_SIZE_HINTS") == 0) + { + output = (char*)buffer; + import = True; + } + else if (strcmp(typeS, "WM_STATE") == 0) + { + /* + * Contents of property of type WM_STATE + * are {CARD32 state, WINDOW icon}. Only + * the icon field has to be modified before + * importing the property. + */ + + WindowPtr pIcon; + + wmState = *(WMState*)buffer; + pIcon = nxagentWindowPtr(wmState.icon); + + if (pIcon || wmState.icon == None) + { + import = True; + output = (char*) &wmState; + wmState.icon = pIcon ? nxagentWindow(pIcon) : None; + } + else if (wmState.icon) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to convert remote window %ld" + " importing property %ld of type WM_STATE", (long int) wmState.icon, + (long int) property); + #endif + } + } + else if (strcmp(typeS, "WM_HINTS") == 0) + { + wmHints = *(XWMHints*)buffer; + output = (char*) &wmHints; + import = True; + + if ((wmHints.flags & IconPixmapHint) && (wmHints.icon_pixmap != None)) + { + PixmapPtr icon = nxagentPixmapPtr(wmHints.icon_pixmap); + + if (icon) + { + wmHints.icon_pixmap = icon -> drawable.id; + } + else + { + wmHints.flags &= ~IconPixmapHint; + + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote icon " + "pixmap %ld from hint importing property [%ld] type %s on window %p.\n", + wmHints.icon_pixmap, (long int) property, typeS, (void *) pWin); + #endif + } + } + + if ((wmHints.flags & IconWindowHint) && (wmHints.icon_window =! None)) + { + WindowPtr icon = nxagentWindowPtr(wmHints.icon_window); + + if (icon) + { + wmHints.icon_window = icon -> drawable.id; + } + else + { + wmHints.flags &= ~IconWindowHint; + + #ifdef WARNING + fprintf(stderr, "nxagenImportProperty: WARNING! Failed to look up remote icon " + "window %lx from hint importing property [%ld] type %s on window %p.\n", + wmHints.icon_window, (long int) property, typeS, (void *) pWin); + #endif + } + } + + if ((wmHints.flags & IconMaskHint) && (wmHints.icon_mask =! None)) + { + PixmapPtr icon = nxagentPixmapPtr(wmHints.icon_mask); + + if (icon) + { + wmHints.icon_mask = icon -> drawable.id; + } + else + { + wmHints.flags &= ~IconMaskHint; + + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote icon " + "mask %lx from hint importing property [%ld] type %s on window %p.\n", + wmHints.icon_mask, (long int) property, typeS, (void *) pWin); + #endif + } + } + + if ((wmHints.flags & WindowGroupHint) && (wmHints.window_group != None)) + { + WindowPtr group = nxagentWindowPtr(wmHints.window_group); + + if (group) + { + wmHints.window_group = group -> drawable.id; + } + else + { + wmHints.flags &= ~WindowGroupHint; + + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote window " + "group %lx from hint importing property [%ld] type %s on window %p.\n", + wmHints.window_group, (long int) property, typeS, (void *) pWin); + #endif + } + } + } + else if (strcmp(typeS, "ATOM") == 0) + { + Atom *atoms = malloc(nitems * sizeof(Atom)); + Atom *input = (Atom*) buffer; + int i; + + if (atoms == NULL) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Malloc failed bailing out.\n"); + #endif + + return; + } + + freeMem = True; + import = True; + output = (char *) atoms; + + for (i = 0; i < nitems; i++) + { + atoms[i] = nxagentRemoteToLocalAtom(input[i]); + + if (atoms[i] == None) + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to convert remote atom %ld.\n", + (long int) input[i]); + #endif + } + } + } + else if (strcmp(typeS, "WINDOW") == 0) + { + Window *input = (Window*) buffer; + Window *wind = malloc(nitems * sizeof(Window)); + WindowPtr pWindow; + int i; + + freeMem = True; + import = True; + output = (char*) wind; + + for (i = 0; i < nitems; i++) + { + pWindow = nxagentWindowPtr(input[i]); + + if (pWindow) + { + wind[i] = pWindow -> drawable.id; + } + else + { + #ifdef WARNING + fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote window %lx " + "importing property [%ld] type %s on window %p.\n", + (long int) input[i], (long int) property, typeS, (void*)pWin); + #endif + + wind[i] = None; + } + } + } + + if (import) + { + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: ChangeProperty " + "on window %lx property [%ld] type %s nitems %ld format %d\n", + window, property, typeS, nitems, format); + #endif + + ChangeWindowProperty(pWin, propertyL, typeL, format, + PropModeReplace, nitems, output, 1); + } + else + { + #ifdef TEST + fprintf(stderr, "nxagentImportProperty: WARNING! Ignored ChangeProperty " + "on window %lx property [%ld] type %s ntems %ld format %d\n", + window, property, validateString(typeS), nitems, format); + #endif + } + + if (freeMem) + { + xfree(output); + } + + return; +} + +/* + * We want to import all properties changed by external clients to + * reflect properties of our internal windows but we must ignore + * all the property notify events generated by our own requests. + * For this purpose we implement a FIFO to record every change pro- + * perty request that we dispatch. In this way, when processing a + * property notify, we can distinguish between the notifications + * generated by our requests from those generated by other clients + * connected to the real X server. + */ + +struct nxagentPropertyRec{ + Window window; + Atom property; + struct nxagentPropertyRec *next; +}; + +static struct{ + struct nxagentPropertyRec *first; + struct nxagentPropertyRec *last; + int size; +} nxagentPropertyList = {NULL, NULL, 0}; + +/* + * Removing first element from list. + */ + +void nxagentRemovePropertyFromList() +{ + struct nxagentPropertyRec *tmp = nxagentPropertyList.first; + + #ifdef TEST + fprintf(stderr, "nxagentRemovePropertyFromList: Property %ld on Window %lx to list, list size is %d.\n\n", + nxagentPropertyList.first -> property, nxagentPropertyList.first -> window, + nxagentPropertyList.size); + #endif + + if (nxagentPropertyList.first) + { + nxagentPropertyList.first = nxagentPropertyList.first -> next; + + if (--nxagentPropertyList.size == 0) + { + nxagentPropertyList.last = NULL; + } + + xfree(tmp); + } +} + +/* + * Add the record to the list. + */ + +void nxagentAddPropertyToList(Atom property, WindowPtr pWin) +{ + struct nxagentPropertyRec *tmp; + + if (NXDisplayError(nxagentDisplay) == 1) + { + return; + } + + if ((tmp = malloc(sizeof(struct nxagentPropertyRec))) == NULL) + { + FatalError("nxagentAddPropertyToList: malloc failed."); + } + + #ifdef TEST + fprintf(stderr, "nxagentAddPropertyToList: Adding record Property %ld - Window %lx[%p]" + "to list, list size is %d.\n", property, nxagentWindow(pWin), (void*) pWin, + nxagentPropertyList.size); + #endif + + tmp -> property = property; + tmp -> window = nxagentWindow(pWin); + tmp -> next = NULL; + + if (nxagentPropertyList.size == 0) + { + nxagentPropertyList.first = tmp; + } + else + { + nxagentPropertyList.last -> next = tmp; + } + + nxagentPropertyList.last = tmp; + nxagentPropertyList.size++; +} + +void nxagentFreePropertyList() +{ + while (nxagentPropertyList.size != 0) + { + nxagentRemovePropertyFromList(); + } +} + +/* + * We are trying to distinguish notify generated by + * an external client from those genarated by our + * own requests. + */ + +Bool nxagentNotifyMatchChangeProperty(void *p) +{ + struct nxagentPropertyRec *first = nxagentPropertyList.first; + XPropertyEvent *X = p; + + #ifdef TEST + fprintf(stderr, "nxagentNotifyMatchChangeProperty: Property notify on window %lx property %ld.\n", + X -> window, X -> atom); + + if (first) + { + fprintf(stderr, "nxagentNotifyMatchChangeProperty: First element on list is window %lx property %ld list size is %d.\n", + first -> window, first -> property, nxagentPropertyList.size); + } + else + { + fprintf(stderr, "nxagentNotifyMatchChangeProperty: List is empty.\n"); + } + #endif + + if (first == NULL || + X -> window != first -> window || + X -> atom != first -> property) + { + return False; + } + + nxagentRemovePropertyFromList(); + + return True; +} + |