]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/Xext/saver.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / Xext / saver.c
1 /*
2  * $XConsortium: saver.c,v 1.12 94/04/17 20:59:36 dpw Exp $
3  * $XFree86: xc/programs/Xserver/Xext/saver.c,v 3.2 1996/06/10 09:11:17 dawes Exp $
4  *
5 Copyright (c) 1992  X Consortium
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
27  *
28  * Author:  Keith Packard, MIT X Consortium
29  */
30
31 #define NEED_REPLIES
32 #define NEED_EVENTS
33 #include <stdio.h>
34 #include "X.h"
35 #include "Xproto.h"
36 #include "misc.h"
37 #include "os.h"
38 #include "windowstr.h"
39 #include "scrnintstr.h"
40 #include "pixmapstr.h"
41 #include "extnsionst.h"
42 #include "dixstruct.h"
43 #include "resource.h"
44 #include "opaque.h"
45 #include "saverproto.h"
46 #include "gcstruct.h"
47 #include "cursorstr.h"
48 #include "colormapst.h"
49
50 static unsigned char ScreenSaverReqCode = 0;
51 static int ScreenSaverEventBase = 0;
52
53 extern DISPATCH_PROC(ProcScreenSaverQueryInfo);
54 static DISPATCH_PROC(ProcScreenSaverDispatch);
55 static DISPATCH_PROC(ProcScreenSaverQueryVersion);
56 static DISPATCH_PROC(ProcScreenSaverSelectInput);
57 static DISPATCH_PROC(ProcScreenSaverSetAttributes);
58 static DISPATCH_PROC(ProcScreenSaverUnsetAttributes);
59 static DISPATCH_PROC(SProcScreenSaverDispatch);
60 static DISPATCH_PROC(SProcScreenSaverQueryInfo);
61 static DISPATCH_PROC(SProcScreenSaverQueryVersion);
62 static DISPATCH_PROC(SProcScreenSaverSelectInput);
63 static DISPATCH_PROC(SProcScreenSaverSetAttributes);
64 static DISPATCH_PROC(SProcScreenSaverUnsetAttributes);
65
66 static Bool ScreenSaverHandle (
67 #if NeedFunctionPrototypes
68         ScreenPtr /* pScreen */,
69         int /* xstate */,
70         Bool /* force */
71 #endif
72         );
73
74 static Bool
75 CreateSaverWindow (
76 #if NeedFunctionPrototypes
77         ScreenPtr /* pScreen */
78 #endif
79         );
80
81 static Bool
82 DestroySaverWindow (
83 #if NeedFunctionPrototypes
84         ScreenPtr /* pScreen */
85 #endif
86         );
87
88 static void
89 UninstallSaverColormap (
90 #if NeedFunctionPrototypes
91         ScreenPtr /* pScreen */
92 #endif
93         );
94
95 static void
96 CheckScreenPrivate (
97 #if NeedFunctionPrototypes
98         ScreenPtr /* pScreen */
99 #endif
100         );
101
102 static void SScreenSaverNotifyEvent (
103 #if NeedFunctionPrototypes
104         xScreenSaverNotifyEvent * /* from */,
105         xScreenSaverNotifyEvent * /* to */
106 #endif
107         );
108
109 static void ScreenSaverResetProc (
110 #if NeedFunctionPrototypes
111         ExtensionEntry * /* extEntry */
112 #endif
113         );
114
115 extern WindowPtr    *WindowTable;
116
117 /*
118  * each screen has a list of clients requesting
119  * ScreenSaverNotify events.  Each client has a resource
120  * for each screen it selects ScreenSaverNotify input for,
121  * this resource is used to delete the ScreenSaverNotifyRec
122  * entry from the per-screen queue.
123  */
124
125 static RESTYPE EventType;   /* resource type for event masks */
126
127 typedef struct _ScreenSaverEvent *ScreenSaverEventPtr;
128
129 typedef struct _ScreenSaverEvent {
130     ScreenSaverEventPtr next;
131     ClientPtr           client;
132     ScreenPtr           screen;
133     XID                 resource;
134     CARD32              mask;
135 } ScreenSaverEventRec;
136
137 static int ScreenSaverFreeEvents(
138 #if NeedFunctionPrototypes
139     pointer /* value */,
140     XID /* id */
141 #endif
142 );
143
144 static Bool setEventMask (
145 #if NeedFunctionPrototypes
146     ScreenPtr /* pScreen */,
147     ClientPtr /* client */,
148     unsigned long /* mask */
149 #endif
150 );
151
152 static unsigned long getEventMask (
153 #if NeedFunctionPrototypes
154     ScreenPtr /* pScreen */,
155     ClientPtr /* client */
156 #endif
157 );
158
159 /*
160  * when a client sets the screen saver attributes, a resource is
161  * kept to be freed when the client exits
162  */
163
164 static RESTYPE AttrType;    /* resource type for attributes */
165
166 typedef struct _ScreenSaverAttr {
167     ScreenPtr       screen;
168     ClientPtr       client;
169     XID             resource;
170     short           x, y;
171     unsigned short  width, height, borderWidth;
172     unsigned char   class;
173     unsigned char   depth;
174     VisualID        visual;
175     CursorPtr       pCursor;
176     PixmapPtr       pBackgroundPixmap;
177     PixmapPtr       pBorderPixmap;
178     Colormap        colormap;
179     unsigned long   mask;               /* no pixmaps or cursors */
180     unsigned long   *values;
181 } ScreenSaverAttrRec, *ScreenSaverAttrPtr;
182
183 static int ScreenSaverFreeAttr (
184 #if NeedFunctionPrototypes
185     pointer /* value */,
186     XID /* id */
187 #endif
188 );
189
190 static void FreeAttrs (
191 #if NeedFunctionPrototypes
192     ScreenSaverAttrPtr  /* pAttr */
193 #endif
194 );
195
196 static void FreeScreenAttr (
197 #if NeedFunctionPrototypes
198     ScreenSaverAttrPtr  /* pAttr */
199 #endif
200 );
201
202 static void
203 SendScreenSaverNotify (
204 #if NeedFunctionPrototypes
205     ScreenPtr /* pScreen */,
206     int /* state */,
207     Bool /* forced */
208 #endif
209 );
210
211 typedef struct _ScreenSaverScreenPrivate {
212     ScreenSaverEventPtr     events;
213     ScreenSaverAttrPtr      attr;
214     Bool                    hasWindow;
215     Colormap                installedMap;
216 } ScreenSaverScreenPrivateRec, *ScreenSaverScreenPrivatePtr;
217
218 static ScreenSaverScreenPrivatePtr
219 MakeScreenPrivate (
220 #if NeedFunctionPrototypes
221         ScreenPtr /* pScreen */
222 #endif
223         );
224
225 static int ScreenPrivateIndex;
226
227 #define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr)(s)->devPrivates[ScreenPrivateIndex].ptr)
228 #define SetScreenPrivate(s,v) ((s)->devPrivates[ScreenPrivateIndex].ptr = (pointer) v);
229 #define SetupScreen(s)  ScreenSaverScreenPrivatePtr pPriv = GetScreenPrivate(s)
230
231 #define New(t)  ((t *) xalloc (sizeof (t)))
232
233 /****************
234  * ScreenSaverExtensionInit
235  *
236  * Called from InitExtensions in main() or from QueryExtension() if the
237  * extension is dynamically loaded.
238  *
239  ****************/
240
241 void
242 ScreenSaverExtensionInit()
243 {
244     ExtensionEntry *extEntry;
245     int             i;
246     ScreenPtr       pScreen;
247
248     AttrType = CreateNewResourceType(ScreenSaverFreeAttr);
249     EventType = CreateNewResourceType(ScreenSaverFreeEvents);
250     ScreenPrivateIndex = AllocateScreenPrivateIndex ();
251     for (i = 0; i < screenInfo.numScreens; i++)
252     {
253         pScreen = screenInfo.screens[i];
254         SetScreenPrivate (pScreen, NULL);
255     }
256     if (AttrType && EventType && ScreenPrivateIndex != -1 &&
257         (extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0,
258                                  ProcScreenSaverDispatch, SProcScreenSaverDispatch,
259                                  ScreenSaverResetProc, StandardMinorOpcode)))
260     {
261         ScreenSaverReqCode = (unsigned char)extEntry->base;
262         ScreenSaverEventBase = extEntry->eventBase;
263         EventSwapVector[ScreenSaverEventBase] = (EventSwapPtr) SScreenSaverNotifyEvent;
264     }
265 }
266
267 /*ARGSUSED*/
268 static void
269 ScreenSaverResetProc (extEntry)
270 ExtensionEntry  *extEntry;
271 {
272 }
273
274 static void
275 CheckScreenPrivate (pScreen)
276     ScreenPtr   pScreen;
277 {
278     SetupScreen (pScreen);
279
280     if (!pPriv)
281         return;
282     if (!pPriv->attr && !pPriv->events &&
283         !pPriv->hasWindow && pPriv->installedMap == None)
284     {
285         xfree (pPriv);
286         SetScreenPrivate (pScreen, NULL);
287         savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL;
288     }
289 }
290
291 static ScreenSaverScreenPrivatePtr
292 MakeScreenPrivate (pScreen)
293     ScreenPtr   pScreen;
294 {
295     SetupScreen (pScreen);
296
297     if (pPriv)
298         return pPriv;
299     pPriv = New (ScreenSaverScreenPrivateRec);
300     if (!pPriv)
301         return 0;
302     pPriv->events = 0;
303     pPriv->attr = 0;
304     pPriv->hasWindow = FALSE;
305     pPriv->installedMap = None;
306     SetScreenPrivate (pScreen, pPriv);
307     savedScreenInfo[pScreen->myNum].ExternalScreenSaver = ScreenSaverHandle;
308     return pPriv;
309 }
310
311 static unsigned long
312 getEventMask (pScreen, client)
313     ScreenPtr   pScreen;
314     ClientPtr   client;
315 {
316     SetupScreen(pScreen);
317     ScreenSaverEventPtr pEv;
318
319     if (!pPriv)
320         return 0;
321     for (pEv = pPriv->events; pEv; pEv = pEv->next)
322         if (pEv->client == client)
323             return pEv->mask;
324     return 0;
325 }
326
327 static Bool
328 setEventMask (pScreen, client, mask)
329     ScreenPtr   pScreen;
330     ClientPtr   client;
331     unsigned long   mask;
332 {
333     SetupScreen(pScreen);
334     ScreenSaverEventPtr pEv, *pPrev;
335
336     if (getEventMask (pScreen, client) == mask)
337         return TRUE;
338     if (!pPriv)
339     {
340         pPriv = MakeScreenPrivate (pScreen);
341         if (!pPriv)
342             return FALSE;
343     }
344     for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
345         if (pEv->client == client)
346             break;
347     if (mask == 0)
348     {
349         FreeResource (pEv->resource, EventType);
350         *pPrev = pEv->next;
351         xfree (pEv);
352         CheckScreenPrivate (pScreen);
353     }
354     else
355     {
356         if (!pEv) 
357         {
358             pEv = New (ScreenSaverEventRec);
359             if (!pEv) 
360             {
361                 CheckScreenPrivate (pScreen);
362                 return FALSE;
363             }
364             *pPrev = pEv;
365             pEv->next = NULL;
366             pEv->client = client;
367             pEv->screen = pScreen;
368             pEv->resource = FakeClientID (client->index);
369             if (!AddResource (pEv->resource, EventType, (pointer) pEv))
370                 return FALSE;
371         }
372         pEv->mask = mask;
373     }
374     return TRUE;
375 }
376
377 static void
378 FreeAttrs (pAttr)
379     ScreenSaverAttrPtr  pAttr;
380 {
381     PixmapPtr       pPixmap;
382     CursorPtr       pCursor;
383
384     if ((pPixmap = pAttr->pBackgroundPixmap) != 0)
385         (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
386     if ((pPixmap = pAttr->pBorderPixmap) != 0)
387         (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
388     if ((pCursor = pAttr->pCursor) != 0)
389         FreeCursor (pCursor, (Cursor) 0);
390 }
391
392 static void
393 FreeScreenAttr (pAttr)
394     ScreenSaverAttrPtr  pAttr;
395 {
396     FreeAttrs (pAttr);
397     xfree (pAttr->values);
398     xfree (pAttr);
399 }
400
401 static int
402 ScreenSaverFreeEvents (value, id)
403     pointer value;
404     XID id;
405 {
406     ScreenSaverEventPtr pOld = (ScreenSaverEventPtr)value;
407     ScreenPtr pScreen = pOld->screen;
408     SetupScreen (pScreen);
409     ScreenSaverEventPtr pEv, *pPrev;
410
411     if (!pPriv)
412         return TRUE;
413     for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
414         if (pEv == pOld)
415             break;
416     if (!pEv)
417         return TRUE;
418     *pPrev = pEv->next;
419     xfree (pEv);
420     CheckScreenPrivate (pScreen);
421     return TRUE;
422 }
423
424 static int
425 ScreenSaverFreeAttr (value, id)
426     pointer value;
427     XID id;
428 {
429     ScreenSaverAttrPtr  pOldAttr = (ScreenSaverAttrPtr)value;
430     ScreenPtr   pScreen = pOldAttr->screen;
431     SetupScreen (pScreen);
432
433     if (!pPriv)
434         return TRUE;
435     if (pPriv->attr != pOldAttr)
436         return TRUE;
437     FreeScreenAttr (pOldAttr);
438     pPriv->attr = NULL;
439     if (pPriv->hasWindow)
440     {
441         SaveScreens (SCREEN_SAVER_FORCER, ScreenSaverReset);
442         SaveScreens (SCREEN_SAVER_FORCER, ScreenSaverActive);
443     }
444     CheckScreenPrivate (pScreen);
445     return TRUE;
446 }
447
448 static void
449 SendScreenSaverNotify (pScreen, state, forced)
450     ScreenPtr                   pScreen;
451     int     state;
452     Bool    forced;
453 {
454     ScreenSaverScreenPrivatePtr pPriv;
455     ScreenSaverEventPtr         pEv;
456     unsigned long               mask;
457     xScreenSaverNotifyEvent     ev;
458     ClientPtr                   client;
459     int                         kind;
460     ScreenSaverStuffPtr         pSaver;
461
462     UpdateCurrentTimeIf ();
463     mask = ScreenSaverNotifyMask;
464     if (state == ScreenSaverCycle)
465         mask = ScreenSaverCycleMask;
466     pScreen = screenInfo.screens[pScreen->myNum];
467     pPriv = GetScreenPrivate(pScreen);
468     if (!pPriv)
469         return;
470     pSaver = &savedScreenInfo[pScreen->myNum];
471     if (pPriv->attr)
472         kind = ScreenSaverExternal;
473     else if (ScreenSaverBlanking != DontPreferBlanking)
474         kind = ScreenSaverBlanked;
475     else
476         kind = ScreenSaverInternal;
477     for (pEv = pPriv->events; pEv; pEv = pEv->next)
478     {
479         client = pEv->client;
480         if (client->clientGone)
481             continue;
482         if (!(pEv->mask & mask))
483             continue;
484         ev.type = ScreenSaverNotify + ScreenSaverEventBase;
485         ev.state = state;
486         ev.sequenceNumber = client->sequence;
487         ev.timestamp = currentTime.milliseconds;
488         ev.root = WindowTable[pScreen->myNum]->drawable.id;
489         ev.window = savedScreenInfo[pScreen->myNum].wid;
490         ev.kind = kind;
491         ev.forced = forced;
492         WriteEventsToClient (client, 1, (xEvent *) &ev);
493     }
494 }
495
496 static void
497 SScreenSaverNotifyEvent (from, to)
498     xScreenSaverNotifyEvent *from, *to;
499 {
500     to->type = from->type;
501     to->state = from->state;
502     cpswaps (from->sequenceNumber, to->sequenceNumber);
503     cpswapl (from->timestamp, to->timestamp);    
504     cpswapl (from->root, to->root);    
505     cpswapl (from->window, to->window);    
506     to->kind = from->kind;
507     to->forced = from->forced;
508 }
509
510 static void
511 UninstallSaverColormap (pScreen)
512     ScreenPtr   pScreen;
513 {
514     SetupScreen(pScreen);
515     ColormapPtr                 pCmap;
516
517     if (pPriv && pPriv->installedMap != None)
518     {
519         pCmap = (ColormapPtr) LookupIDByType (pPriv->installedMap, RT_COLORMAP);
520         if (pCmap)
521             (*pCmap->pScreen->UninstallColormap) (pCmap);
522         pPriv->installedMap = None;
523         CheckScreenPrivate (pScreen);
524     }
525 }
526
527 static Bool
528 CreateSaverWindow (pScreen)
529     ScreenPtr   pScreen;
530 {
531     SetupScreen (pScreen);
532     ScreenSaverStuffPtr         pSaver;
533     ScreenSaverAttrPtr          pAttr;
534     WindowPtr                   pWin;
535     int                         result;
536     unsigned long               mask;
537     extern int                  GrabInProgress;
538     Colormap                    *installedMaps;
539     int                         numInstalled;
540     int                         i;
541     Colormap                    wantMap;
542     ColormapPtr                 pCmap;
543
544     pSaver = &savedScreenInfo[pScreen->myNum];
545     if (pSaver->pWindow)
546     {
547         pSaver->pWindow = NullWindow;
548         FreeResource (pSaver->wid, RT_NONE);
549         if (pPriv)
550         {
551             UninstallSaverColormap (pScreen);
552             pPriv->hasWindow = FALSE;
553             CheckScreenPrivate (pScreen);
554         }
555     }
556
557     if (!pPriv || !(pAttr = pPriv->attr))
558         return FALSE;
559
560     pPriv->installedMap = None;
561
562     if (GrabInProgress && GrabInProgress != pAttr->client->index)
563         return FALSE;
564
565     pWin = CreateWindow (pSaver->wid, WindowTable[pScreen->myNum],
566                          pAttr->x, pAttr->y, pAttr->width, pAttr->height,
567                          pAttr->borderWidth, pAttr->class, 
568                          pAttr->mask, (XID *)pAttr->values, 
569                          pAttr->depth, serverClient, pAttr->visual, 
570                          &result);
571     if (!pWin)
572         return FALSE;
573
574     if (!AddResource(pWin->drawable.id, RT_WINDOW, pWin))
575         return FALSE;
576
577     mask = 0;
578     if (pAttr->pBackgroundPixmap)
579     {
580         pWin->backgroundState = BackgroundPixmap;
581         pWin->background.pixmap = pAttr->pBackgroundPixmap;
582         pAttr->pBackgroundPixmap->refcnt++;
583         mask |= CWBackPixmap;
584     }
585     if (pAttr->pBorderPixmap)
586     {
587         pWin->borderIsPixel = FALSE;
588         pWin->border.pixmap = pAttr->pBorderPixmap;
589         pAttr->pBorderPixmap->refcnt++;
590         mask |= CWBorderPixmap;
591     }
592     if (pAttr->pCursor)
593     {
594         if (!pWin->optional)
595             if (!MakeWindowOptional (pWin))
596             {
597                 FreeResource (pWin->drawable.id, RT_NONE);
598                 return FALSE;
599             }
600         if (pWin->optional->cursor)
601             FreeCursor (pWin->optional->cursor, (Cursor)0);
602         pWin->optional->cursor = pAttr->pCursor;
603         pAttr->pCursor->refcnt++;
604         pWin->cursorIsNone = FALSE;
605         CheckWindowOptionalNeed (pWin);
606         mask |= CWCursor;
607     }
608     if (mask)
609         (*pScreen->ChangeWindowAttributes) (pWin, mask);
610
611     if (pAttr->colormap != None)
612         (void) ChangeWindowAttributes (pWin, CWColormap, &pAttr->colormap,
613                                        serverClient);
614
615     MapWindow (pWin, serverClient);
616
617     pPriv->hasWindow = TRUE;
618     pSaver->pWindow = pWin;
619
620     /* check and install our own colormap if it isn't installed now */
621     wantMap = wColormap (pWin);
622     if (wantMap == None)
623         return TRUE;
624     installedMaps = (Colormap *) ALLOCATE_LOCAL (pScreen->maxInstalledCmaps *
625                                                  sizeof (Colormap));
626     numInstalled = (*pWin->drawable.pScreen->ListInstalledColormaps)
627                                                     (pScreen, installedMaps);
628     for (i = 0; i < numInstalled; i++) 
629         if (installedMaps[i] == wantMap)
630             break;
631
632     DEALLOCATE_LOCAL ((char *) installedMaps);
633
634     if (i < numInstalled)
635         return TRUE;
636
637     pCmap = (ColormapPtr) LookupIDByType (wantMap, RT_COLORMAP);
638     if (!pCmap)
639         return TRUE;
640
641     pPriv->installedMap = wantMap;
642
643     (*pCmap->pScreen->InstallColormap) (pCmap);
644
645     return TRUE;
646 }
647
648 static Bool
649 DestroySaverWindow (pScreen)
650     ScreenPtr   pScreen;
651 {
652     SetupScreen(pScreen);
653     ScreenSaverStuffPtr         pSaver;
654
655     if (!pPriv || !pPriv->hasWindow)
656         return FALSE;
657
658     pSaver = &savedScreenInfo[pScreen->myNum];
659     if (pSaver->pWindow)
660     {
661         pSaver->pWindow = NullWindow;
662         FreeResource (pSaver->wid, RT_NONE);
663     }
664     pPriv->hasWindow = FALSE;
665     CheckScreenPrivate (pScreen);
666     UninstallSaverColormap (pScreen);
667     return TRUE;
668 }
669
670 static Bool
671 ScreenSaverHandle (pScreen, xstate, force)
672     ScreenPtr   pScreen;
673     int         xstate;
674     Bool        force;
675 {
676     int                         state;
677     Bool                        ret = FALSE;
678     ScreenSaverScreenPrivatePtr pPriv;
679
680     switch (xstate)
681     {
682     case SCREEN_SAVER_ON:       
683         state = ScreenSaverOn;
684         ret = CreateSaverWindow (pScreen);
685         break;
686     case SCREEN_SAVER_OFF:      
687         state = ScreenSaverOff;
688         ret = DestroySaverWindow (pScreen);
689         break;
690     case SCREEN_SAVER_CYCLE:    
691         state = ScreenSaverCycle;
692         pPriv = GetScreenPrivate (pScreen);
693         if (pPriv && pPriv->hasWindow)
694             ret = TRUE;
695         
696     }
697     SendScreenSaverNotify (pScreen, state, force);
698     return ret;
699 }
700
701 static int
702 ProcScreenSaverQueryVersion (client)
703     register ClientPtr  client;
704 {
705     xScreenSaverQueryVersionReply       rep;
706     register int                n;
707
708     REQUEST_SIZE_MATCH (xScreenSaverQueryVersionReq);
709     rep.type = X_Reply;
710     rep.length = 0;
711     rep.sequenceNumber = client->sequence;
712     rep.majorVersion = ScreenSaverMajorVersion;
713     rep.minorVersion = ScreenSaverMinorVersion;
714     if (client->swapped) {
715         swaps(&rep.sequenceNumber, n);
716         swapl(&rep.length, n);
717     }
718     WriteToClient(client, sizeof (xScreenSaverQueryVersionReply), (char *)&rep);
719     return (client->noClientException);
720 }
721
722 int
723 ProcScreenSaverQueryInfo (client)
724     register ClientPtr  client;
725 {
726     REQUEST(xScreenSaverQueryInfoReq);
727     xScreenSaverQueryInfoReply  rep;
728     register int                n;
729     ScreenSaverStuffPtr         pSaver;
730     DrawablePtr                 pDraw;
731     CARD32                      lastInput;
732     ScreenSaverScreenPrivatePtr pPriv;
733
734     REQUEST_SIZE_MATCH (xScreenSaverQueryInfoReq);
735     pDraw = (DrawablePtr) LookupDrawable (stuff->drawable, client);
736     if (!pDraw)
737         return BadDrawable;
738
739     pSaver = &savedScreenInfo[pDraw->pScreen->myNum];
740     pPriv = GetScreenPrivate (pDraw->pScreen);
741
742     UpdateCurrentTime ();
743     lastInput = GetTimeInMillis() - lastDeviceEventTime.milliseconds;
744
745     rep.type = X_Reply;
746     rep.length = 0;
747     rep.sequenceNumber = client->sequence;
748     rep.window = pSaver->wid;
749     if (screenIsSaved != SCREEN_SAVER_OFF)
750     {
751         rep.state = ScreenSaverOn;
752         if (ScreenSaverTime)
753             rep.tilOrSince = lastInput - ScreenSaverTime;
754         else
755             rep.tilOrSince = 0;
756     }
757     else
758     {
759         if (ScreenSaverTime)
760         {
761             rep.state = ScreenSaverOff;
762             if (ScreenSaverTime < lastInput)
763                 rep.tilOrSince = 0;
764             else
765                 rep.tilOrSince = ScreenSaverTime - lastInput;
766         }
767         else
768         {
769             rep.state = ScreenSaverDisabled;
770             rep.tilOrSince = 0;
771         }
772     }
773     rep.idle = lastInput;
774     rep.eventMask = getEventMask (pDraw->pScreen, client);
775     if (pPriv && pPriv->attr)
776         rep.kind = ScreenSaverExternal;
777     else if (ScreenSaverBlanking != DontPreferBlanking)
778         rep.kind = ScreenSaverBlanked;
779     else
780         rep.kind = ScreenSaverInternal;
781     if (client->swapped)
782     {
783         swaps (&rep.sequenceNumber, n);
784         swapl (&rep.length, n);
785         swapl (&rep.window, n);
786         swapl (&rep.tilOrSince, n);
787         swapl (&rep.idle, n);
788         swapl (&rep.eventMask, n);
789     }
790     WriteToClient(client, sizeof (xScreenSaverQueryInfoReply), (char *)&rep);
791     return (client->noClientException);
792 }
793
794 static int
795 ProcScreenSaverSelectInput (client)
796     register ClientPtr  client;
797 {
798     REQUEST(xScreenSaverSelectInputReq);
799     DrawablePtr                 pDraw;
800
801     REQUEST_SIZE_MATCH (xScreenSaverSelectInputReq);
802     pDraw = (DrawablePtr) LookupDrawable (stuff->drawable, client);
803     if (!pDraw)
804         return BadDrawable;
805     if (!setEventMask (pDraw->pScreen, client, stuff->eventMask))
806         return BadAlloc;
807     return Success;
808 }
809
810 static int
811 ProcScreenSaverSetAttributes (client)
812     register ClientPtr  client;
813 {
814     REQUEST(xScreenSaverSetAttributesReq);
815     DrawablePtr                 pDraw;
816     WindowPtr                   pParent;
817     ScreenPtr                   pScreen;
818     ScreenSaverScreenPrivatePtr pPriv = 0;
819     ScreenSaverAttrPtr          pAttr = 0;
820     int                         ret;
821     int                         len;
822     int                         class, bw, depth;
823     unsigned long               visual;
824     int                         idepth, ivisual;
825     Bool                        fOK;
826     DepthPtr                    pDepth;
827     WindowOptPtr                ancwopt;
828     unsigned long               *pVlist;
829     unsigned long               *values = 0;
830     int                         valuei;
831     unsigned long               tmask, imask;
832     unsigned long               val;
833     Pixmap                      pixID;
834     PixmapPtr                   pPixmap;
835     Cursor                      cursorID;
836     CursorPtr                   pCursor;
837     Colormap                    cmap;
838     ColormapPtr                 pCmap;
839
840     REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq);
841     pDraw = (DrawablePtr) LookupDrawable (stuff->drawable, client);
842     if (!pDraw)
843         return BadDrawable;
844     pScreen = pDraw->pScreen;
845     pParent = WindowTable[pScreen->myNum];
846
847     len = stuff->length -  (sizeof(xScreenSaverSetAttributesReq) >> 2);
848     if (Ones(stuff->mask) != len)
849         return BadLength;
850     if (!stuff->width || !stuff->height)
851     {
852         client->errorValue = 0;
853         return BadValue;
854     }
855     switch (class = stuff->c_class) 
856     {
857     case CopyFromParent:
858     case InputOnly:
859     case InputOutput:
860         break;
861     default:
862         client->errorValue = class;
863         return BadValue;
864     }
865     bw = stuff->borderWidth;
866     depth = stuff->depth;
867     visual = stuff->visualID;
868
869     /* copied directly from CreateWindow */
870
871     if (class == CopyFromParent)
872         class = pParent->drawable.class;
873
874     if ((class != InputOutput) && (class != InputOnly))
875     {
876         client->errorValue = class;
877         return BadValue;
878     }
879
880     if ((class != InputOnly) && (pParent->drawable.class == InputOnly))
881         return BadMatch;
882
883     if ((class == InputOnly) && ((bw != 0) || (depth != 0)))
884         return BadMatch;
885
886     if ((class == InputOutput) && (depth == 0))
887         depth = pParent->drawable.depth;
888     ancwopt = pParent->optional;
889     if (!ancwopt)
890         ancwopt = FindWindowWithOptional(pParent)->optional;
891     if (visual == CopyFromParent)
892         visual = ancwopt->visual;
893
894     /* Find out if the depth and visual are acceptable for this Screen */
895     if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth))
896     {
897         fOK = FALSE;
898         for(idepth = 0; idepth < pScreen->numDepths; idepth++)
899         {
900             pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
901             if ((depth == pDepth->depth) || (depth == 0))
902             {
903                 for (ivisual = 0; ivisual < pDepth->numVids; ivisual++)
904                 {
905                     if (visual == pDepth->vids[ivisual])
906                     {
907                         fOK = TRUE;
908                         break;
909                     }
910                 }
911             }
912         }
913         if (fOK == FALSE)
914             return BadMatch;
915     }
916
917     if (((stuff->mask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
918         (class != InputOnly) &&
919         (depth != pParent->drawable.depth))
920     {
921         return BadMatch;
922     }
923
924     if (((stuff->mask & CWColormap) == 0) &&
925         (class != InputOnly) &&
926         ((visual != ancwopt->visual) || (ancwopt->colormap == None)))
927     {
928         return BadMatch;
929     }
930
931     /* end of errors from CreateWindow */
932
933     pPriv = GetScreenPrivate (pScreen);
934     if (pPriv && pPriv->attr)
935     {
936         if (pPriv->attr->client != client)
937             return BadAccess;
938     }
939     if (!pPriv)
940     {
941         pPriv = MakeScreenPrivate (pScreen);
942         if (!pPriv)
943             return FALSE;
944     }
945     pAttr = New (ScreenSaverAttrRec);
946     if (!pAttr)
947     {
948         ret = BadAlloc;
949         goto bail;
950     }
951     /* over allocate for override redirect */
952     values = (unsigned long *) xalloc ((len + 1) * sizeof (unsigned long));
953     if (!values)
954     {
955         ret = BadAlloc;
956         goto bail;
957     }
958     valuei = 0;
959     pAttr->screen = pScreen;
960     pAttr->client = client;
961     pAttr->x = stuff->x;
962     pAttr->y = stuff->y;
963     pAttr->width = stuff->width;
964     pAttr->height = stuff->height;
965     pAttr->borderWidth = stuff->borderWidth;
966     pAttr->class = stuff->c_class;
967     pAttr->depth = depth;
968     pAttr->visual = visual;
969     pAttr->colormap = None;
970     pAttr->pCursor = NullCursor;
971     pAttr->pBackgroundPixmap = NullPixmap;
972     pAttr->pBorderPixmap = NullPixmap;
973     pAttr->values = values;
974     /*
975      * go through the mask, checking the values,
976      * looking up pixmaps and cursors and hold a reference
977      * to them.
978      */
979     pAttr->mask = tmask = stuff->mask | CWOverrideRedirect;
980     pVlist = (unsigned long *) (stuff + 1);
981     while (tmask) {
982         imask = lowbit (tmask);
983         tmask &= ~imask;
984         switch (imask)
985         {
986         case CWBackPixmap:
987             pixID = (Pixmap )*pVlist;
988             if (pixID == None)
989             {
990                 *values++ = None;
991             }
992             else if (pixID == ParentRelative)
993             {
994                 if (depth != pParent->drawable.depth)
995                 {
996                     ret = BadMatch;
997                     goto PatchUp;
998                 }
999                 *values++ = ParentRelative;
1000             }
1001             else
1002             {   
1003                 pPixmap = (PixmapPtr)LookupIDByType(pixID, RT_PIXMAP);
1004                 if (pPixmap != (PixmapPtr) NULL)
1005                 {
1006                     if  ((pPixmap->drawable.depth != depth) ||
1007                          (pPixmap->drawable.pScreen != pScreen))
1008                     {
1009                         ret = BadMatch;
1010                         goto PatchUp;
1011                     }
1012                     pAttr->pBackgroundPixmap = pPixmap;
1013                     pPixmap->refcnt++;
1014                     pAttr->mask &= ~CWBackPixmap;
1015                 }
1016                 else
1017                 {
1018                     ret = BadPixmap;
1019                     client->errorValue = pixID;
1020                     goto PatchUp;
1021                 }
1022             }
1023             break;
1024         case CWBackPixel:
1025             *values++ = (CARD32) *pVlist;
1026             break;
1027         case CWBorderPixmap:
1028             pixID = (Pixmap ) *pVlist;
1029             if (pixID == CopyFromParent)
1030             {
1031                 if (depth != pParent->drawable.depth)
1032                 {
1033                     ret = BadMatch;
1034                     goto PatchUp;
1035                 }
1036                 *values++ = CopyFromParent;
1037             }
1038             else
1039             {   
1040                 pPixmap = (PixmapPtr)LookupIDByType(pixID, RT_PIXMAP);
1041                 if (pPixmap)
1042                 {
1043                     if  ((pPixmap->drawable.depth != depth) ||
1044                          (pPixmap->drawable.pScreen != pScreen))
1045                     {
1046                         ret = BadMatch;
1047                         goto PatchUp;
1048                     }
1049                     pAttr->pBorderPixmap = pPixmap;
1050                     pPixmap->refcnt++;
1051                     pAttr->mask &= ~CWBorderPixmap;
1052                 }
1053                 else
1054                 {
1055                     ret = BadPixmap;
1056                     client->errorValue = pixID;
1057                     goto PatchUp;
1058                 }
1059             }
1060             break;
1061         case CWBorderPixel:
1062             *values++ = (CARD32) *pVlist;
1063             break;
1064         case CWBitGravity:
1065             val = (CARD8 )*pVlist;
1066             if (val > StaticGravity)
1067             {
1068                 ret = BadValue;
1069                 client->errorValue = val;
1070                 goto PatchUp;
1071             }
1072             *values++ = val;
1073             break;
1074         case CWWinGravity:
1075             val = (CARD8 )*pVlist;
1076             if (val > StaticGravity)
1077             {
1078                 ret = BadValue;
1079                 client->errorValue = val;
1080                 goto PatchUp;
1081             }
1082             *values++ = val;
1083             break;
1084         case CWBackingStore:
1085             val = (CARD8 )*pVlist;
1086             if ((val != NotUseful) && (val != WhenMapped) && (val != Always))
1087             {
1088                 ret = BadValue;
1089                 client->errorValue = val;
1090                 goto PatchUp;
1091             }
1092             *values++ = val;
1093             break;
1094         case CWBackingPlanes:
1095             *values++ = (CARD32) *pVlist;
1096             break;
1097         case CWBackingPixel:
1098             *values++ = (CARD32) *pVlist;
1099             break;
1100         case CWSaveUnder:
1101             val = (BOOL) *pVlist;
1102             if ((val != xTrue) && (val != xFalse))
1103             {
1104                 ret = BadValue;
1105                 client->errorValue = val;
1106                 goto PatchUp;
1107             }
1108             *values++ = val;
1109             break;
1110         case CWEventMask:
1111             *values++ = (CARD32) *pVlist;
1112             break;
1113         case CWDontPropagate:
1114             *values++ = (CARD32) *pVlist;
1115             break;
1116         case CWOverrideRedirect:
1117             if (!(stuff->mask & CWOverrideRedirect))
1118                 pVlist--;
1119             else
1120             {
1121                 val = (BOOL ) *pVlist;
1122                 if ((val != xTrue) && (val != xFalse))
1123                 {
1124                     ret = BadValue;
1125                     client->errorValue = val;
1126                     goto PatchUp;
1127                 }
1128             }
1129             *values++ = xTrue;
1130             break;
1131         case CWColormap:
1132             cmap = (Colormap) *pVlist;
1133             pCmap = (ColormapPtr)LookupIDByType(cmap, RT_COLORMAP);
1134             if (!pCmap)
1135             {
1136                 ret = BadColor;
1137                 client->errorValue = cmap;
1138                 goto PatchUp;
1139             }
1140             if (pCmap->pVisual->vid != visual || pCmap->pScreen != pScreen)
1141             {
1142                 ret = BadMatch;
1143                 goto PatchUp;
1144             }
1145             pAttr->colormap = cmap;
1146             pAttr->mask &= ~CWColormap;
1147             break;
1148         case CWCursor:
1149             cursorID = (Cursor ) *pVlist;
1150             if ( cursorID == None)
1151             {
1152                 *values++ = None;
1153             }
1154             else
1155             {
1156                 pCursor = (CursorPtr)LookupIDByType(cursorID, RT_CURSOR);
1157                 if (!pCursor)
1158                 {
1159                     ret = BadCursor;
1160                     client->errorValue = cursorID;
1161                     goto PatchUp;
1162                 }
1163                 pCursor->refcnt++;
1164                 pAttr->pCursor = pCursor;
1165                 pAttr->mask &= ~CWCursor;
1166             }
1167             break;
1168          default:
1169             ret = BadValue;
1170             client->errorValue = stuff->mask;
1171             goto PatchUp;
1172         }
1173         pVlist++;
1174     }
1175     if (pPriv->attr)
1176         FreeScreenAttr (pPriv->attr);
1177     pPriv->attr = pAttr;
1178     pAttr->resource = FakeClientID (client->index);
1179     if (!AddResource (pAttr->resource, AttrType, (pointer) pAttr))
1180         return BadAlloc;
1181     return Success;
1182 PatchUp:
1183     FreeAttrs (pAttr);
1184 bail:
1185     CheckScreenPrivate (pScreen);
1186     xfree (pAttr);
1187     xfree (values);
1188     return ret;
1189 }
1190
1191 static int
1192 ProcScreenSaverUnsetAttributes (client)
1193     register ClientPtr  client;
1194 {
1195     REQUEST(xScreenSaverSetAttributesReq);
1196     DrawablePtr                 pDraw;
1197     ScreenSaverScreenPrivatePtr pPriv;
1198
1199     REQUEST_SIZE_MATCH (xScreenSaverUnsetAttributesReq);
1200     pDraw = (DrawablePtr) LookupDrawable (stuff->drawable, client);
1201     if (!pDraw)
1202         return BadDrawable;
1203     pPriv = GetScreenPrivate (pDraw->pScreen);
1204     if (pPriv && pPriv->attr && pPriv->attr->client == client)
1205     {
1206         FreeScreenAttr (pPriv->attr);
1207         pPriv->attr = NULL;
1208         CheckScreenPrivate (pDraw->pScreen);
1209     }
1210     return Success;
1211 }
1212
1213 static DISPATCH_PROC((*NormalVector[])) = {
1214     ProcScreenSaverQueryVersion,
1215     ProcScreenSaverQueryInfo,
1216     ProcScreenSaverSelectInput,
1217     ProcScreenSaverSetAttributes,
1218     ProcScreenSaverUnsetAttributes,
1219 };
1220
1221 #define NUM_REQUESTS    ((sizeof NormalVector) / (sizeof NormalVector[0]))
1222
1223 static int
1224 ProcScreenSaverDispatch (client)
1225     ClientPtr   client;
1226 {
1227     REQUEST(xReq);
1228
1229     if (stuff->data < NUM_REQUESTS)
1230         return (*NormalVector[stuff->data])(client);
1231     return BadRequest;
1232 }
1233
1234 static int
1235 SProcScreenSaverQueryVersion (client)
1236     ClientPtr   client;
1237 {
1238     REQUEST(xScreenSaverQueryVersionReq);
1239     int     n;
1240
1241     swaps (&stuff->length, n);
1242     REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq);
1243     return ProcScreenSaverQueryVersion (client);
1244 }
1245
1246 static int
1247 SProcScreenSaverQueryInfo (client)
1248     ClientPtr   client;
1249 {
1250     REQUEST(xScreenSaverQueryInfoReq);
1251     int     n;
1252
1253     swaps (&stuff->length, n);
1254     REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq);
1255     swapl (&stuff->drawable, n);
1256     return ProcScreenSaverQueryInfo (client);
1257 }
1258
1259 static int
1260 SProcScreenSaverSelectInput (client)
1261     ClientPtr   client;
1262 {
1263     REQUEST(xScreenSaverSelectInputReq);
1264     int     n;
1265
1266     swaps (&stuff->length, n);
1267     REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq);
1268     swapl (&stuff->drawable, n);
1269     swapl (&stuff->eventMask, n);
1270     return ProcScreenSaverSelectInput (client);
1271 }
1272
1273 static int
1274 SProcScreenSaverSetAttributes (client)
1275     ClientPtr   client;
1276 {
1277     REQUEST(xScreenSaverSetAttributesReq);
1278     int     n;
1279
1280     swaps (&stuff->length, n);
1281     REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq);
1282     swapl (&stuff->drawable, n);
1283     swaps (&stuff->x, n);
1284     swaps (&stuff->y, n);
1285     swaps (&stuff->width, n);
1286     swaps (&stuff->height, n);
1287     swaps (&stuff->borderWidth, n);
1288     swapl (&stuff->visualID, n);
1289     swapl (&stuff->mask, n);
1290     SwapRestL(stuff);
1291     return ProcScreenSaverSetAttributes (client);
1292 }
1293
1294 static int
1295 SProcScreenSaverUnsetAttributes (client)
1296     ClientPtr   client;
1297 {
1298     REQUEST(xScreenSaverUnsetAttributesReq);
1299     int     n;
1300
1301     swaps (&stuff->length, n);
1302     REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq);
1303     swapl (&stuff->drawable, n);
1304     return ProcScreenSaverUnsetAttributes (client);
1305 }
1306
1307 static DISPATCH_PROC((*SwappedVector[])) = {
1308     SProcScreenSaverQueryVersion,
1309     SProcScreenSaverQueryInfo,
1310     SProcScreenSaverSelectInput,
1311     SProcScreenSaverSetAttributes,
1312     SProcScreenSaverUnsetAttributes,
1313 };
1314
1315 static int
1316 SProcScreenSaverDispatch (client)
1317     ClientPtr   client;
1318 {
1319     REQUEST(xReq);
1320
1321     if (stuff->data < NUM_REQUESTS)
1322         return (*SwappedVector[stuff->data])(client);
1323     return BadRequest;
1324 }