--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c.X.original 2015-02-13 14:03:44.740441589 +0100 +++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXdispatch.c 2015-02-13 14:03:44.740441589 +0100 @@ -1,3 +1,20 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of Medialogic S.p.A. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + /* $XdotOrg: xc/programs/Xserver/dix/dispatch.c,v 1.13 2005/09/13 01:33:19 daniels Exp $ */ /* $Xorg: dispatch.c,v 1.5 2001/02/09 02:04:40 xorgcvs Exp $ */ /************************************************************ @@ -87,6 +104,15 @@ int ProcInitialConnection(); #endif +#ifdef __sun +#define False 0 +#define True 1 +#endif + +#define GC XlibGC +#include <X11/Xlib.h> +#undef GC + #include "windowstr.h" #include <X11/fonts/fontstruct.h> #include "dixfontstr.h" @@ -100,7 +126,7 @@ #include "servermd.h" #include "extnsionst.h" #include "dixfont.h" -#include "dispatch.h" +#include "../../dix/dispatch.h" #include "swaprep.h" #include "swapreq.h" #ifdef PANORAMIX @@ -119,8 +145,69 @@ #include "inputstr.h" #include <X11/extensions/XKBsrv.h> #endif + +#include "Atoms.h" +#include "Splash.h" +#include "Client.h" +#include "Clipboard.h" +#include "Reconnect.h" +#include "Millis.h" +#include "Font.h" +#include "Shadow.h" +#include "Handlers.h" +#include "Keyboard.h" + +const int nxagentMaxFontNames = 10000; + +char dispatchExceptionAtReset = DE_RESET; + +/* + * This allows the agent to exit if no + * client is connected within a timeout. + */ + +int nxagentClients = 0; + +void nxagentWaitDisplay(void); + +void nxagentListRemoteFonts(const char *, int); + +unsigned int nxagentWMtimeout = 0; +Bool nxagentWMPassed = 0; + +/* + * Timeouts based on screen saver time. + */ + +int nxagentAutoDisconnectTimeout = 0; + #ifdef LBX -#include "lbxserve.h" +#include "../../lbx/lbxserve.h" +#endif + +#include "Xatom.h" + +/* + * Set here the required log level. + */ + +#define PANIC +#define WARNING +#undef TEST +#undef WATCH + +/* + * Log begin and end of the important handlers. + */ + +#undef BLOCKS + +#ifdef WATCH +#include "unistd.h" +#endif + +#ifdef TEST +#include "Literals.h" #endif #define mskcnt ((MAXCLIENTS + 31) / 32) @@ -138,6 +225,28 @@ int NumCurrentSelections; CallbackListPtr SelectionCallback = NULL; +#ifdef VIEWPORT_FRAME + +extern WindowPtr nxagentViewportFrameLeft; +extern WindowPtr nxagentViewportFrameRight; +extern WindowPtr nxagentViewportFrameAbove; +extern WindowPtr nxagentViewportFrameBelow; + +#define IsViewportFrame(pWin) ((pWin) == nxagentViewportFrameLeft || \ + (pWin) == nxagentViewportFrameRight || \ + (pWin) == nxagentViewportFrameAbove || \ + (pWin) == nxagentViewportFrameBelow) + +#else + +#define IsViewportFrame(pWin) (0) + +#endif /* #ifdef VIEWPORT_FRAME */ + +extern int nxagentMaxAllowedResets; + +extern int nxagentFindClientResource(int, RESTYPE, pointer); + static ClientPtr grabClient; #define GrabNone 0 #define GrabActive 1 @@ -222,6 +331,30 @@ xfree(CurrentSelections); CurrentSelections = (Selection *)NULL; NumCurrentSelections = 0; + +#ifdef NXAGENT_CLIPBOARD + { + Selection *newsels; + newsels = (Selection *)xalloc(2 * sizeof(Selection)); + if (!newsels) + return; + NumCurrentSelections += 2; + CurrentSelections = newsels; + + CurrentSelections[0].selection = XA_PRIMARY; + CurrentSelections[0].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[0].window = WindowTable[0]->drawable.id; + CurrentSelections[0].pWin = NULL; + CurrentSelections[0].client = NullClient; + + CurrentSelections[1].selection = MakeAtom("CLIPBOARD", 9, 1); + CurrentSelections[1].lastTimeChanged = ClientTimeToServerTime(0); + CurrentSelections[1].window = WindowTable[0]->drawable.id; + CurrentSelections[1].pWin = NULL; + CurrentSelections[1].client = NullClient; + } +#endif + } void @@ -369,14 +502,72 @@ long start_tick; #endif + unsigned long currentDispatch = 0; + nextFreeClientID = 1; InitSelections(); nClients = 0; + /* + * The agent initialization was successfully + * completed. We can now handle our clients. + */ + + #ifdef XKB + + nxagentInitXkbWrapper(); + + nxagentTuneXkbWrapper(); + + #endif + + #ifdef NXAGENT_ONSTART + + /* + * Set NX_WM property (used by NX client to identify + * the agent's window) three seconds since the first + * client connects. + */ + + nxagentWMtimeout = GetTimeInMillis() + 3000; + + #endif + clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients); if (!clientReady) return; + #ifdef WATCH + + fprintf(stderr, "Dispatch: Watchpoint 12.\n"); + +/* +Reply Total Cached Bits In Bits Out Bits/Reply Ratio +------- ----- ------ ------- -------- ---------- ----- +#3 1 352 bits (0 KB) -> 236 bits (0 KB) -> 352/1 -> 236/1 = 1.492:1 +#14 1 256 bits (0 KB) -> 101 bits (0 KB) -> 256/1 -> 101/1 = 2.535:1 +#16 1 256 bits (0 KB) -> 26 bits (0 KB) -> 256/1 -> 26/1 = 9.846:1 +#20 2 2 12256 bits (1 KB) -> 56 bits (0 KB) -> 6128/1 -> 28/1 = 218.857:1 +#43 1 256 bits (0 KB) -> 45 bits (0 KB) -> 256/1 -> 45/1 = 5.689:1 +#47 2 2 42304 bits (5 KB) -> 49 bits (0 KB) -> 21152/1 -> 24/1 = 863.347:1 +#98 1 256 bits (0 KB) -> 34 bits (0 KB) -> 256/1 -> 34/1 = 7.529:1 +*/ + + sleep(30); + + #endif + + #ifdef TEST + fprintf(stderr, "Dispatch: Value of dispatchException is [%x].\n", + dispatchException); + + fprintf(stderr, "Dispatch: Value of dispatchExceptionAtReset is [%x].\n", + dispatchExceptionAtReset); + #endif + + if (!(dispatchException & DE_TERMINATE)) + dispatchException = 0; + while (!dispatchException) { if (*icheck[0] != *icheck[1]) @@ -385,8 +576,75 @@ FlushIfCriticalOutputPending(); } + /* + * Ensure we remove the splash after the timeout. + * Initializing clientReady[0] to -1 will tell + * WaitForSomething() to yield control after the + * timeout set in clientReady[1]. + */ + + clientReady[0] = 0; + + if (nxagentSplashWindow != None || (nxagentOption(Xdmcp) == 1 && nxagentXdmcpUp == 0)) + { + #ifdef TEST + fprintf(stderr, "******Dispatch: Requesting a timeout of [%d] Ms.\n", + NXAGENT_WAKEUP); + #endif + + clientReady[0] = -1; + clientReady[1] = NXAGENT_WAKEUP; + } + + if (serverGeneration > nxagentMaxAllowedResets && + nxagentSessionState == SESSION_STARTING && + (nxagentOption(Xdmcp) == 0 || nxagentXdmcpUp == 1)) + { + #ifdef NX_DEBUG_INPUT + fprintf(stderr, "Session: Session started at '%s' timestamp [%lu].\n", + GetTimeAsString(), GetTimeInMillis()); + #else + fprintf(stderr, "Session: Session started at '%s'.\n", + GetTimeAsString()); + #endif + + nxagentSessionState = SESSION_UP; + } + + #ifdef BLOCKS + fprintf(stderr, "[End dispatch]\n"); + #endif + nready = WaitForSomething(clientReady); + #ifdef BLOCKS + fprintf(stderr, "[Begin dispatch]\n"); + #endif + + #ifdef TEST + fprintf(stderr, "******Dispatch: Running with [%d] clients ready.\n", + nready); + #endif + + #ifdef NXAGENT_ONSTART + + currentDispatch = GetTimeInMillis(); + + /* + * If the timeout is expired set the + * selection informing the NX client + * that the agent is ready. + */ + + if (!nxagentWMPassed && (nxagentWMtimeout < currentDispatch)) + { + nxagentRemoveSplashWindow(NULL); + } + + nxagentClients = nClients; + + #endif + #ifdef SMART_SCHEDULE if (nready && !SmartScheduleDisable) { @@ -438,6 +696,11 @@ #endif /* now, finally, deal with client requests */ + #ifdef TEST + fprintf(stderr, "******Dispatch: Reading request from client [%d].\n", + client->index); + #endif + result = ReadRequestFromClient(client); if (result <= 0) { @@ -445,6 +708,29 @@ CloseDownClient(client); break; } +#ifdef NXAGENT_SERVER + + #ifdef TEST + + else + { + + if (MAJOROP > 127) + { + fprintf(stderr, "******Dispatch: Read [Extension] request OPCODE#%d MINOR#%d " + "size [%d] client [%d].\n", MAJOROP, *((char *) client->requestBuffer + 1), + client->req_len << 2, client->index); + } + else + { + fprintf(stderr, "******Dispatch: Read [%s] request OPCODE#%d size [%d] client [%d].\n", + nxagentRequestLiteral[MAJOROP], MAJOROP, client->req_len << 2, + client->index); + } + } + + #endif +#endif client->sequence++; #ifdef DEBUG @@ -456,8 +742,40 @@ if (result > (maxBigRequestSize << 2)) result = BadLength; else +#ifdef NXAGENT_SERVER + { + result = (* client->requestVector[MAJOROP])(client); + + #ifdef TEST + + if (MAJOROP > 127) + { + fprintf(stderr, "******Dispatch: Handled [Extension] request OPCODE#%d MINOR#%d " + "size [%d] client [%d] result [%d].\n", MAJOROP, + *((char *) client->requestBuffer + 1), client->req_len << 2, + client->index, result); + } + else + { + fprintf(stderr, "******Dispatch: Handled [%s] request OPCODE#%d size [%d] client [%d] " + "result [%d].\n", nxagentRequestLiteral[MAJOROP], MAJOROP, + client->req_len << 2, client->index, result); + } + + #endif + + /* + * Can set isItTimeToYield to force + * the dispatcher to pay attention + * to another client. + */ + + nxagentDispatchHandler(client, client->req_len << 2, 0); + } +#else result = (* client->requestVector[MAJOROP])(client); - +#endif + if (result != Success) { if (client->noClientException != Success) @@ -485,6 +803,37 @@ #if defined(DDXBEFORERESET) ddxBeforeReset (); #endif + if ((dispatchException & DE_RESET) && + (serverGeneration > nxagentMaxAllowedResets)) + { + dispatchException &= ~DE_RESET; + dispatchException |= DE_TERMINATE; + + fprintf(stderr, "Info: Reached threshold of maximum allowed resets.\n"); + } + + nxagentResetAtomMap(); + + if (serverGeneration > nxagentMaxAllowedResets) + { + /* + * The session is terminating. Force an I/O + * error on the display and wait until the + * NX transport is gone. + */ + + fprintf(stderr, "Session: Terminating session at '%s'.\n", GetTimeAsString()); + + nxagentWaitDisplay(); + + fprintf(stderr, "Session: Session terminated at '%s'.\n", GetTimeAsString()); + } + + if (nxagentOption(Shadow) == 1) + { + NXShadowDestroy(); + } + KillAllClients(); DEALLOCATE_LOCAL(clientReady); dispatchException &= ~DE_RESET; @@ -656,6 +1005,12 @@ SecurityWriteAccess); if (!pWin) return(BadWindow); + + if (!nxagentWMPassed) + { + nxagentRemoveSplashWindow(pWin); + } + pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client, SecurityWriteAccess); if (!pParent) @@ -724,6 +1079,7 @@ return(BadWindow); UnmapWindow(pWin, FALSE); /* update cache to say it is mapped */ + return(client->noClientException); } @@ -760,6 +1116,7 @@ return BadLength; result = ConfigureWindow(pWin, (Mask)stuff->mask, (XID *) &stuff[1], client); + if (client->noClientException != Success) return(client->noClientException); else @@ -865,7 +1222,12 @@ reply.parent = (Window)None; pHead = RealChildHead(pWin); for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (!IsViewportFrame(pChild)) + { numChildren++; + } + } if (numChildren) { int curChild = 0; @@ -874,7 +1236,12 @@ if (!childIDs) return BadAlloc; for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) + { + if (!IsViewportFrame(pChild)) + { childIDs[curChild++] = pChild->drawable.id; + } + } } reply.nChildren = numChildren; @@ -1038,6 +1405,16 @@ info.kind= SelectionSetOwner; CallCallbacks(&SelectionCallback, &info); } + +#ifdef NXAGENT_CLIPBOARD + if ((CurrentSelections[i].pWin != NULL) && + (nxagentOption(Clipboard) != ClipboardNone) && + ((CurrentSelections[i].selection == XA_PRIMARY) || + (CurrentSelections[i].selection == MakeAtom("CLIPBOARD", 9, 0)))) + { + nxagentSetSelectionOwner(&CurrentSelections[i]); + } +#endif return (client->noClientException); } else @@ -1092,6 +1469,27 @@ if (!pWin) return(BadWindow); +#ifdef NXAGENT_CLIPBOARD + if (((stuff->selection == XA_PRIMARY) || + (stuff->selection == MakeAtom("CLIPBOARD", 9, 0))) && + nxagentOption(Clipboard) != ClipboardNone) + { + int i = 0; + + while ((i < NumCurrentSelections) && + CurrentSelections[i].selection != stuff->selection) i++; + + if ((i < NumCurrentSelections) && (CurrentSelections[i].window != None)) + { + if (nxagentConvertSelection(client, pWin, stuff->selection, stuff->requestor, + stuff->property, stuff->target, stuff->time)) + { + return (client->noClientException); + } + } + } +#endif + paramsOkay = (ValidAtom(stuff->selection) && ValidAtom(stuff->target)); if (stuff->property != None) paramsOkay &= ValidAtom(stuff->property); @@ -1103,7 +1501,7 @@ while ((i < NumCurrentSelections) && CurrentSelections[i].selection != stuff->selection) i++; if ((i < NumCurrentSelections) && - (CurrentSelections[i].window != None) + (CurrentSelections[i].window != None) && (CurrentSelections[i].client != NullClient) #ifdef XCSECURITY && (!client->CheckAccess || (* client->CheckAccess)(client, CurrentSelections[i].window, @@ -1286,11 +1684,26 @@ ProcOpenFont(register ClientPtr client) { int err; + char fontReq[256]; REQUEST(xOpenFontReq); REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); client->errorValue = stuff->fid; LEGAL_NEW_RESOURCE(stuff->fid, client); + + memcpy(fontReq,(char *)&stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + fontReq[stuff->nbytes]=0; + if (strchr(fontReq,'*') || strchr(fontReq,'?')) + { + extern int nxOpenFont(ClientPtr, XID, Mask, unsigned, char*); +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ProcOpenFont try to find a common font with font pattern=%s\n",fontReq); +#endif + nxagentListRemoteFonts(fontReq, nxagentMaxFontNames); + err = nxOpenFont(client, stuff->fid, (Mask) 0, + stuff->nbytes, (char *)&stuff[1]); + } + else err = OpenFont(client, stuff->fid, (Mask) 0, stuff->nbytes, (char *)&stuff[1]); if (err == Success) @@ -1310,8 +1723,43 @@ REQUEST_SIZE_MATCH(xResourceReq); pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, SecurityDestroyAccess); - if ( pFont != (FontPtr)NULL) /* id was valid */ + if (pFont != (FontPtr)NULL) { + #ifdef NXAGENT_SERVER + + /* + * When a client closes a font the resource + * should not be lost if the reference counter + * is not 0, otherwise the server will not be + * able to find this font looping through the + * resources. + */ + + if (pFont -> refcnt > 0) + { + if (nxagentFindClientResource(serverClient -> index, RT_NX_FONT, pFont) == 0) + { + #ifdef TEST + fprintf(stderr, "ProcCloseFont: Switching resource for font at [%p].\n", + (void *) pFont); + #endif + + nxagentFontPriv(pFont) -> mirrorID = FakeClientID(serverClient -> index); + + AddResource(nxagentFontPriv(pFont) -> mirrorID, RT_NX_FONT, pFont); + + } + #ifdef TEST + else + { + fprintf(stderr, "ProcCloseFont: Found duplicated font at [%p], " + "resource switching skipped.\n", (void *) pFont); + } + #endif + } + + #endif + FreeResource(stuff->id, RT_NONE); return(client->noClientException); } @@ -1332,6 +1780,8 @@ REQUEST_SIZE_MATCH(xResourceReq); client->errorValue = stuff->id; /* EITHER font or gc */ + + pFont = NULL; pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, SecurityReadAccess); if (!pFont) @@ -1347,6 +1797,33 @@ pFont = pGC->font; } +/* test +{ + Atom name_atom, value_atom; + int nprops; + FontPropPtr props; + int i; + char *name; + + name_atom = MakeAtom("FONT", 4, True); + value_atom = 0L; + + nprops = pFont->info.nprops; + props = pFont->info.props; + + for (i = 0; i < nprops; i++) + if (props[i].name == name_atom) { + value_atom = props[i].value; + break; + } + + if (!value_atom) return (BadFont); + + name = (char *)NameForAtom(value_atom); + fprintf(stderr, "QueryFont: font name [%s]\n",name); +} + end test */ + { xCharInfo *pmax = FONTINKMAX(pFont); xCharInfo *pmin = FONTINKMIN(pFont); @@ -1364,6 +1841,7 @@ rlength = sizeof(xQueryFontReply) + FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + nprotoxcistructs * sizeof(xCharInfo); + reply = NULL; reply = (xQueryFontReply *)ALLOCATE_LOCAL(rlength); if(!reply) { @@ -1434,10 +1912,18 @@ int ProcListFonts(register ClientPtr client) { + char tmp[256]; + REQUEST(xListFontsReq); REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); + memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + tmp[stuff->nbytes]=0; +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ListFont request with pattern %s max_names=%d\n",tmp,stuff->maxNames); +#endif + nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames : stuff->maxNames); return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, stuff->maxNames); } @@ -1445,10 +1931,18 @@ int ProcListFontsWithInfo(register ClientPtr client) { + char tmp[256]; REQUEST(xListFontsWithInfoReq); REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); + memcpy(tmp,(unsigned char *) &stuff[1],(stuff->nbytes<256)?stuff->nbytes:255); + tmp[stuff->nbytes]=0; +#ifdef NXAGENT_FONTMATCH_DEBUG + fprintf(stderr, "Dispatch: ListFont with info request with pattern %s max_names=%d\n",tmp,stuff->maxNames); +#endif + nxagentListRemoteFonts(tmp, stuff -> maxNames < nxagentMaxFontNames ? nxagentMaxFontNames :stuff->maxNames); + return StartListFontsWithInfo(client, stuff->nbytes, (unsigned char *) &stuff[1], stuff->maxNames); } @@ -1535,6 +2029,40 @@ SecurityDestroyAccess); if (pMap) { + #ifdef NXAGENT_SERVER + + /* + * When a client releases a pixmap the resource + * should not be lost if the reference counter + * is not 0, otherwise the server will not be + * able to find this pixmap looping through the + * resources. + */ + + if (pMap -> refcnt > 0) + { + if (nxagentFindClientResource(serverClient -> index, RT_NX_PIXMAP, pMap) == 0) + { + #ifdef TEST + fprintf(stderr, "ProcFreePixmap: Switching resource for pixmap at [%p].\n", + (void *) pMap); + #endif + + nxagentPixmapPriv(pMap) -> mid = FakeClientID(serverClient -> index); + + AddResource(nxagentPixmapPriv(pMap) -> mid, RT_NX_PIXMAP, pMap); + } + #ifdef TEST + else + { + fprintf(stderr, "ProcFreePixmap: Found duplicated pixmap at [%p], " + "resource switching skipped.\n", (void *) pMap); + } + #endif + } + + #endif + FreeResource(stuff->id, RT_NONE); return(client->noClientException); } @@ -1819,8 +2347,10 @@ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2; if (npoint) + { (*pGC->ops->PolyPoint)(pDraw, pGC, stuff->coordMode, npoint, (xPoint *) &stuff[1]); + } return (client->noClientException); } @@ -1842,8 +2372,10 @@ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2; if (npoint > 1) + { (*pGC->ops->Polylines)(pDraw, pGC, stuff->coordMode, npoint, (DDXPointPtr) &stuff[1]); + } return(client->noClientException); } @@ -1862,7 +2394,9 @@ return(BadLength); nsegs >>= 3; if (nsegs) + { (*pGC->ops->PolySegment)(pDraw, pGC, nsegs, (xSegment *) &stuff[1]); + } return (client->noClientException); } @@ -1881,8 +2415,10 @@ return(BadLength); nrects >>= 3; if (nrects) + { (*pGC->ops->PolyRectangle)(pDraw, pGC, nrects, (xRectangle *) &stuff[1]); + } return(client->noClientException); } @@ -1901,7 +2437,9 @@ return(BadLength); narcs /= sizeof(xArc); if (narcs) + { (*pGC->ops->PolyArc)(pDraw, pGC, narcs, (xArc *) &stuff[1]); + } return (client->noClientException); } @@ -1930,9 +2468,11 @@ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client); things = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2; if (things) + { (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, stuff->coordMode, things, (DDXPointPtr) &stuff[1]); + } return(client->noClientException); } @@ -1952,8 +2492,10 @@ things >>= 3; if (things) + { (*pGC->ops->PolyFillRect) (pDraw, pGC, things, (xRectangle *) &stuff[1]); + } return (client->noClientException); } @@ -1972,7 +2514,9 @@ return(BadLength); narcs /= sizeof(xArc); if (narcs) + { (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); + } return (client->noClientException); } @@ -3127,7 +3671,14 @@ stuff->backRed, stuff->backGreen, stuff->backBlue); if (pCursor && AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) + { + #ifdef TEST + fprintf(stderr, "ProcCreateCursor: Created cursor at [%p].\n", (void *) pCursor); + #endif + return (client->noClientException); + } + return BadAlloc; } @@ -3243,25 +3794,68 @@ return BadValue; } - if (blankingOption == DefaultBlanking) + /* + * The NX agent uses the screen saver procedure + * to monitor the user activities and launch its + * handlers (like timeout feature), so we can't + * always allow the clients to change our values. + */ + + #ifdef TEST + fprintf(stderr, "ProcSetScreenSaver: Called with timeout [%d] interval [%d] Blanking [%d] Exposure [%d].\n", + stuff -> timeout, stuff -> interval, blankingOption, exposureOption); + #endif + + if (nxagentOption(Timeout) == 0) + { + if (blankingOption == DefaultBlanking) + { ScreenSaverBlanking = defaultScreenSaverBlanking; - else + } + else + { ScreenSaverBlanking = blankingOption; - if (exposureOption == DefaultExposures) + } + + if (exposureOption == DefaultExposures) + { ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; - else - ScreenSaverAllowExposures = exposureOption; + } + else + { + ScreenSaverAllowExposures = exposureOption; + } + + if (stuff->timeout >= 0) + { + ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; + } + else + { + ScreenSaverTime = defaultScreenSaverTime; + } + + if (stuff->interval >= 0) + { + ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; + } + else + { + ScreenSaverInterval = defaultScreenSaverInterval; + } + + SetScreenSaverTimer(); + } + #ifdef TEST - if (stuff->timeout >= 0) - ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; - else - ScreenSaverTime = defaultScreenSaverTime; - if (stuff->interval >= 0) - ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; else - ScreenSaverInterval = defaultScreenSaverInterval; + { + fprintf(stderr, "ProcSetScreenSaver: Keeping auto-disconnect timeout set to [%d] seconds.\n", + nxagentOption(Timeout)); + } + + #endif - SetScreenSaverTimer(); return (client->noClientException); } @@ -3481,7 +4075,30 @@ client->errorValue = stuff->mode; return BadValue; } - SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode); + + /* + * The NX agent uses the screen saver procedure + * to monitor the user activities and launch its + * handlers (like timeout feature), so we can't + * always allow the clients to force the screen + * saver handler execution. + */ + + if (nxagentOption(Timeout) == 0) + { + SaveScreens(SCREEN_SAVER_FORCER, (int)stuff->mode); + } + + #ifdef TEST + + else + { + fprintf(stderr, "ProcForceScreenSaver: Ignoring the client request with mode [%d].\n", + stuff -> mode); + } + + #endif + return client->noClientException; } @@ -3525,14 +4142,34 @@ * then killed again, the client is really destroyed. *********************/ -char dispatchExceptionAtReset = DE_RESET; - void CloseDownClient(register ClientPtr client) { Bool really_close_down = client->clientGone || client->closeDownMode == DestroyAll; + /* + * There must be a better way to hook a + * call-back function to be called any + * time a client is going to be closed. + */ + + nxagentClearClipboard(client, NULL); + + /* + * Need to reset the karma counter and + * get rid of the pending sync replies. + */ + + nxagentWakeupByReset(client); + + /* + * Check if the client + * is a shadow nxagent. + */ + + nxagentCheckIfShadowAgent(client); + if (!client->clientGone) { /* ungrab server if grabbing client dies */ @@ -3673,7 +4310,7 @@ client->numSaved = 0; client->saveSet = (SaveSetElt *)NULL; client->noClientException = Success; -#ifdef DEBUG +#ifdef LOG_DEBUG client->requestLogIndex = 0; #endif client->requestVector = InitialVector; @@ -3746,6 +4383,13 @@ else ppriv->ptr = (pointer)NULL; } + + /* + * Initialize the private members. + */ + + nxagentInitClientPrivates(client); + return 1; }