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