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