| 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 | } |