Commit | Line | Data |
---|---|---|
a09e091a JB |
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 | } |