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