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