1370 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1370 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  *
 | |
| Copyright (c) 1992  X Consortium
 | |
| 
 | |
| Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
| of this software and associated documentation files (the "Software"), to deal
 | |
| in the Software without restriction, including without limitation the rights
 | |
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
| copies of the Software, and to permit persons to whom the Software is
 | |
| furnished to do so, subject to the following conditions:
 | |
| 
 | |
| The above copyright notice and this permission notice shall be included in
 | |
| all copies or substantial portions of the Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | |
| X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | |
| AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | |
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | |
| 
 | |
| Except as contained in this notice, the name of the X Consortium shall not be
 | |
| used in advertising or otherwise to promote the sale, use or other dealings
 | |
| in this Software without prior written authorization from the X Consortium.
 | |
|  *
 | |
|  * Author:  Keith Packard, MIT X Consortium
 | |
|  */
 | |
| 
 | |
| #include <dix-config.h>
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <X11/X.h>
 | |
| #include <X11/Xproto.h>
 | |
| #include <X11/extensions/saverproto.h>
 | |
| 
 | |
| #include "dix/colormap_priv.h"
 | |
| #include "dix/cursor_priv.h"
 | |
| #include "dix/dix_priv.h"
 | |
| #include "os/osdep.h"
 | |
| #include "os/screensaver.h"
 | |
| 
 | |
| #include "misc.h"
 | |
| #include "os.h"
 | |
| #include "windowstr.h"
 | |
| #include "scrnintstr.h"
 | |
| #include "pixmapstr.h"
 | |
| #include "extnsionst.h"
 | |
| #include "dixstruct.h"
 | |
| #include "resource.h"
 | |
| #include "gcstruct.h"
 | |
| #include "cursorstr.h"
 | |
| #include "colormapst.h"
 | |
| #include "xace.h"
 | |
| #include "inputstr.h"
 | |
| #ifdef XINERAMA
 | |
| #include "panoramiX.h"
 | |
| #include "panoramiXsrv.h"
 | |
| #endif /* XINERAMA */
 | |
| #ifdef DPMSExtension
 | |
| #include <X11/extensions/dpmsconst.h>
 | |
| #include "dpmsproc.h"
 | |
| #endif
 | |
| #include "protocol-versions.h"
 | |
| #include "extinit_priv.h"
 | |
| 
 | |
| // temporary workaround for win32/mingw32 name clash
 | |
| // see: https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1355
 | |
| #undef CreateWindow
 | |
| 
 | |
| Bool noScreenSaverExtension = FALSE;
 | |
| 
 | |
| static int ScreenSaverEventBase = 0;
 | |
| 
 | |
| static Bool ScreenSaverHandle(ScreenPtr pScreen, int xstate, Bool force);
 | |
| static Bool CreateSaverWindow(ScreenPtr pScreen);
 | |
| static Bool DestroySaverWindow(ScreenPtr pScreen);
 | |
| static void UninstallSaverColormap(ScreenPtr pScreen);
 | |
| static void CheckScreenPrivate(ScreenPtr pScreen);
 | |
| static void SScreenSaverNotifyEvent(xScreenSaverNotifyEvent *from,
 | |
|                                     xScreenSaverNotifyEvent *to);
 | |
| 
 | |
| static RESTYPE SuspendType;     /* resource type for suspension records */
 | |
| 
 | |
| typedef struct _ScreenSaverSuspension *ScreenSaverSuspensionPtr;
 | |
| 
 | |
| /* List of clients that are suspending the screensaver. */
 | |
| static ScreenSaverSuspensionPtr suspendingClients = NULL;
 | |
| 
 | |
| /*
 | |
|  * clientResource is a resource ID that's added when the record is
 | |
|  * allocated, so the record is freed and the screensaver resumed when
 | |
|  * the client disconnects. count is the number of times the client has
 | |
|  * requested the screensaver be suspended.
 | |
|  */
 | |
| typedef struct _ScreenSaverSuspension {
 | |
|     ScreenSaverSuspensionPtr next;
 | |
|     ClientPtr pClient;
 | |
|     XID clientResource;
 | |
|     int count;
 | |
| } ScreenSaverSuspensionRec;
 | |
| 
 | |
| static int ScreenSaverFreeSuspend(void *value, XID id);
 | |
| 
 | |
| /*
 | |
|  * each screen has a list of clients requesting
 | |
|  * ScreenSaverNotify events.  Each client has a resource
 | |
|  * for each screen it selects ScreenSaverNotify input for,
 | |
|  * this resource is used to delete the ScreenSaverNotifyRec
 | |
|  * entry from the per-screen queue.
 | |
|  */
 | |
| 
 | |
| static RESTYPE SaverEventType;  /* resource type for event masks */
 | |
| 
 | |
| typedef struct _ScreenSaverEvent *ScreenSaverEventPtr;
 | |
| 
 | |
| typedef struct _ScreenSaverEvent {
 | |
|     ScreenSaverEventPtr next;
 | |
|     ClientPtr client;
 | |
|     ScreenPtr screen;
 | |
|     XID resource;
 | |
|     CARD32 mask;
 | |
| } ScreenSaverEventRec;
 | |
| 
 | |
| static int ScreenSaverFreeEvents(void * value, XID id);
 | |
| 
 | |
| static Bool setEventMask(ScreenPtr      pScreen,
 | |
|                          ClientPtr      client,
 | |
|                          unsigned long  mask);
 | |
| 
 | |
| static unsigned long getEventMask(ScreenPtr     pScreen,
 | |
|                                   ClientPtr     client);
 | |
| 
 | |
| /*
 | |
|  * when a client sets the screen saver attributes, a resource is
 | |
|  * kept to be freed when the client exits
 | |
|  */
 | |
| 
 | |
| static RESTYPE AttrType;        /* resource type for attributes */
 | |
| 
 | |
| typedef struct _ScreenSaverAttr {
 | |
|     ScreenPtr screen;
 | |
|     ClientPtr client;
 | |
|     XID resource;
 | |
|     short x, y;
 | |
|     unsigned short width, height, borderWidth;
 | |
|     unsigned char class;
 | |
|     unsigned char depth;
 | |
|     VisualID visual;
 | |
|     CursorPtr pCursor;
 | |
|     PixmapPtr pBackgroundPixmap;
 | |
|     PixmapPtr pBorderPixmap;
 | |
|     Colormap colormap;
 | |
|     unsigned long mask;         /* no pixmaps or cursors */
 | |
|     unsigned long *values;
 | |
| } ScreenSaverAttrRec, *ScreenSaverAttrPtr;
 | |
| 
 | |
| static int ScreenSaverFreeAttr(void *value, XID id);
 | |
| 
 | |
| static void FreeAttrs(ScreenSaverAttrPtr pAttr);
 | |
| 
 | |
| static void FreeScreenAttr(ScreenSaverAttrPtr pAttr);
 | |
| 
 | |
| static void
 | |
| SendScreenSaverNotify(ScreenPtr pScreen,
 | |
|                       int       state,
 | |
|                       Bool      forced);
 | |
| 
 | |
| typedef struct _ScreenSaverScreenPrivate {
 | |
|     ScreenSaverEventPtr events;
 | |
|     ScreenSaverAttrPtr attr;
 | |
|     Bool hasWindow;
 | |
|     Colormap installedMap;
 | |
| } ScreenSaverScreenPrivateRec, *ScreenSaverScreenPrivatePtr;
 | |
| 
 | |
| static ScreenSaverScreenPrivatePtr MakeScreenPrivate(ScreenPtr pScreen);
 | |
| 
 | |
| static DevPrivateKeyRec ScreenPrivateKeyRec;
 | |
| 
 | |
| #define ScreenPrivateKey (&ScreenPrivateKeyRec)
 | |
| 
 | |
| #define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr) \
 | |
|     dixLookupPrivate(&(s)->devPrivates, ScreenPrivateKey))
 | |
| #define SetScreenPrivate(s,v) \
 | |
|     dixSetPrivate(&(s)->devPrivates, ScreenPrivateKey, v);
 | |
| #define SetupScreen(s)	ScreenSaverScreenPrivatePtr pPriv = (s ? GetScreenPrivate(s) : NULL)
 | |
| 
 | |
| static void
 | |
| CheckScreenPrivate(ScreenPtr pScreen)
 | |
| {
 | |
|     SetupScreen(pScreen);
 | |
| 
 | |
|     if (!pPriv)
 | |
|         return;
 | |
|     if (!pPriv->attr && !pPriv->events &&
 | |
|         !pPriv->hasWindow && pPriv->installedMap == None) {
 | |
|         free(pPriv);
 | |
|         SetScreenPrivate(pScreen, NULL);
 | |
|         pScreen->screensaver.ExternalScreenSaver = NULL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static ScreenSaverScreenPrivatePtr
 | |
| MakeScreenPrivate(ScreenPtr pScreen)
 | |
| {
 | |
|     SetupScreen(pScreen);
 | |
| 
 | |
|     if (pPriv)
 | |
|         return pPriv;
 | |
|     pPriv = calloc(1, sizeof(ScreenSaverScreenPrivateRec));
 | |
|     if (!pPriv)
 | |
|         return 0;
 | |
|     pPriv->events = 0;
 | |
|     pPriv->attr = 0;
 | |
|     pPriv->hasWindow = FALSE;
 | |
|     pPriv->installedMap = None;
 | |
|     SetScreenPrivate(pScreen, pPriv);
 | |
|     pScreen->screensaver.ExternalScreenSaver = ScreenSaverHandle;
 | |
|     return pPriv;
 | |
| }
 | |
| 
 | |
| static unsigned long
 | |
| getEventMask(ScreenPtr pScreen, ClientPtr client)
 | |
| {
 | |
|     SetupScreen(pScreen);
 | |
|     ScreenSaverEventPtr pEv;
 | |
| 
 | |
|     if (!pPriv)
 | |
|         return 0;
 | |
|     for (pEv = pPriv->events; pEv; pEv = pEv->next)
 | |
|         if (pEv->client == client)
 | |
|             return pEv->mask;
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| setEventMask(ScreenPtr pScreen, ClientPtr client, unsigned long mask)
 | |
| {
 | |
|     SetupScreen(pScreen);
 | |
|     ScreenSaverEventPtr pEv, *pPrev;
 | |
| 
 | |
|     if (getEventMask(pScreen, client) == mask)
 | |
|         return TRUE;
 | |
|     if (!pPriv) {
 | |
|         pPriv = MakeScreenPrivate(pScreen);
 | |
|         if (!pPriv)
 | |
|             return FALSE;
 | |
|     }
 | |
|     for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
 | |
|         if (pEv->client == client)
 | |
|             break;
 | |
|     if (mask == 0) {
 | |
|         FreeResource(pEv->resource, SaverEventType);
 | |
|         *pPrev = pEv->next;
 | |
|         free(pEv);
 | |
|         CheckScreenPrivate(pScreen);
 | |
|     }
 | |
|     else {
 | |
|         if (!pEv) {
 | |
|             pEv = calloc(1, sizeof(ScreenSaverEventRec));
 | |
|             if (!pEv) {
 | |
|                 CheckScreenPrivate(pScreen);
 | |
|                 return FALSE;
 | |
|             }
 | |
|             *pPrev = pEv;
 | |
|             pEv->next = NULL;
 | |
|             pEv->client = client;
 | |
|             pEv->screen = pScreen;
 | |
|             pEv->resource = FakeClientID(client->index);
 | |
|             if (!AddResource(pEv->resource, SaverEventType, (void *) pEv))
 | |
|                 return FALSE;
 | |
|         }
 | |
|         pEv->mask = mask;
 | |
|     }
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| FreeAttrs(ScreenSaverAttrPtr pAttr)
 | |
| {
 | |
|     CursorPtr pCursor;
 | |
| 
 | |
|     dixDestroyPixmap(pAttr->pBackgroundPixmap, 0);
 | |
|     dixDestroyPixmap(pAttr->pBorderPixmap, 0);
 | |
|     if ((pCursor = pAttr->pCursor) != 0)
 | |
|         FreeCursor(pCursor, (Cursor) 0);
 | |
| }
 | |
| 
 | |
| static void
 | |
| FreeScreenAttr(ScreenSaverAttrPtr pAttr)
 | |
| {
 | |
|     FreeAttrs(pAttr);
 | |
|     free(pAttr->values);
 | |
|     free(pAttr);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ScreenSaverFreeEvents(void *value, XID id)
 | |
| {
 | |
|     ScreenSaverEventPtr pOld = (ScreenSaverEventPtr) value;
 | |
|     ScreenPtr pScreen = pOld->screen;
 | |
| 
 | |
|     SetupScreen(pScreen);
 | |
|     ScreenSaverEventPtr pEv, *pPrev;
 | |
| 
 | |
|     if (!pPriv)
 | |
|         return TRUE;
 | |
|     for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next)
 | |
|         if (pEv == pOld)
 | |
|             break;
 | |
|     if (!pEv)
 | |
|         return TRUE;
 | |
|     *pPrev = pEv->next;
 | |
|     free(pEv);
 | |
|     CheckScreenPrivate(pScreen);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ScreenSaverFreeAttr(void *value, XID id)
 | |
| {
 | |
|     ScreenSaverAttrPtr pOldAttr = (ScreenSaverAttrPtr) value;
 | |
|     ScreenPtr pScreen = pOldAttr->screen;
 | |
| 
 | |
|     SetupScreen(pScreen);
 | |
| 
 | |
|     if (!pPriv)
 | |
|         return TRUE;
 | |
|     if (pPriv->attr != pOldAttr)
 | |
|         return TRUE;
 | |
|     FreeScreenAttr(pOldAttr);
 | |
|     pPriv->attr = NULL;
 | |
|     if (pPriv->hasWindow) {
 | |
|         dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
 | |
|         dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverActive);
 | |
|     }
 | |
|     CheckScreenPrivate(pScreen);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ScreenSaverFreeSuspend(void *value, XID id)
 | |
| {
 | |
|     ScreenSaverSuspensionPtr data = (ScreenSaverSuspensionPtr) value;
 | |
|     ScreenSaverSuspensionPtr *prev, this;
 | |
| 
 | |
|     /* Unlink and free the suspension record for the client */
 | |
|     for (prev = &suspendingClients; (this = *prev); prev = &this->next) {
 | |
|         if (this == data) {
 | |
|             *prev = this->next;
 | |
|             free(this);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* Re-enable the screensaver if this was the last client suspending it. */
 | |
|     if (screenSaverSuspended && suspendingClients == NULL) {
 | |
|         screenSaverSuspended = FALSE;
 | |
| 
 | |
|         /* The screensaver could be active, since suspending it (by design)
 | |
|            doesn't prevent it from being forceably activated */
 | |
| #ifdef DPMSExtension
 | |
|         if (screenIsSaved != SCREEN_SAVER_ON && DPMSPowerLevel == DPMSModeOn)
 | |
| #else
 | |
|         if (screenIsSaved != SCREEN_SAVER_ON)
 | |
| #endif
 | |
|         {
 | |
|             DeviceIntPtr dev;
 | |
|             UpdateCurrentTimeIf();
 | |
|             nt_list_for_each_entry(dev, inputInfo.devices, next)
 | |
|                 NoticeTime(dev, currentTime);
 | |
|             SetScreenSaverTimer();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static void
 | |
| SendScreenSaverNotify(ScreenPtr pScreen, int state, Bool forced)
 | |
| {
 | |
|     ScreenSaverScreenPrivatePtr pPriv;
 | |
|     ScreenSaverEventPtr pEv;
 | |
|     unsigned long mask;
 | |
|     int kind;
 | |
| 
 | |
|     UpdateCurrentTimeIf();
 | |
|     mask = ScreenSaverNotifyMask;
 | |
|     if (state == ScreenSaverCycle)
 | |
|         mask = ScreenSaverCycleMask;
 | |
|     pScreen = screenInfo.screens[pScreen->myNum];
 | |
|     pPriv = GetScreenPrivate(pScreen);
 | |
|     if (!pPriv)
 | |
|         return;
 | |
|     if (pPriv->attr)
 | |
|         kind = ScreenSaverExternal;
 | |
|     else if (ScreenSaverBlanking != DontPreferBlanking)
 | |
|         kind = ScreenSaverBlanked;
 | |
|     else
 | |
|         kind = ScreenSaverInternal;
 | |
|     for (pEv = pPriv->events; pEv; pEv = pEv->next) {
 | |
|         if (pEv->mask & mask) {
 | |
|             xScreenSaverNotifyEvent ev = {
 | |
|                 .type = ScreenSaverNotify + ScreenSaverEventBase,
 | |
|                 .state = state,
 | |
|                 .timestamp = currentTime.milliseconds,
 | |
|                 .root = pScreen->root->drawable.id,
 | |
|                 .window = pScreen->screensaver.wid,
 | |
|                 .kind = kind,
 | |
|                 .forced = forced
 | |
|             };
 | |
|             WriteEventsToClient(pEv->client, 1, (xEvent *) &ev);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void _X_COLD
 | |
| SScreenSaverNotifyEvent(xScreenSaverNotifyEvent * from,
 | |
|                         xScreenSaverNotifyEvent * to)
 | |
| {
 | |
|     to->type = from->type;
 | |
|     to->state = from->state;
 | |
|     cpswaps(from->sequenceNumber, to->sequenceNumber);
 | |
|     cpswapl(from->timestamp, to->timestamp);
 | |
|     cpswapl(from->root, to->root);
 | |
|     cpswapl(from->window, to->window);
 | |
|     to->kind = from->kind;
 | |
|     to->forced = from->forced;
 | |
| }
 | |
| 
 | |
| static void
 | |
| UninstallSaverColormap(ScreenPtr pScreen)
 | |
| {
 | |
|     SetupScreen(pScreen);
 | |
|     ColormapPtr pCmap;
 | |
|     int rc;
 | |
| 
 | |
|     if (pPriv && pPriv->installedMap != None) {
 | |
|         rc = dixLookupResourceByType((void **) &pCmap, pPriv->installedMap,
 | |
|                                      X11_RESTYPE_COLORMAP, serverClient,
 | |
|                                      DixUninstallAccess);
 | |
|         if (rc == Success)
 | |
|             (*pCmap->pScreen->UninstallColormap) (pCmap);
 | |
|         pPriv->installedMap = None;
 | |
|         CheckScreenPrivate(pScreen);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| CreateSaverWindow(ScreenPtr pScreen)
 | |
| {
 | |
|     SetupScreen(pScreen);
 | |
|     ScreenSaverStuffPtr pSaver;
 | |
|     ScreenSaverAttrPtr pAttr;
 | |
|     WindowPtr pWin;
 | |
|     int result;
 | |
|     unsigned long mask;
 | |
|     Colormap wantMap;
 | |
|     ColormapPtr pCmap;
 | |
| 
 | |
|     pSaver = &pScreen->screensaver;
 | |
|     if (pSaver->pWindow) {
 | |
|         pSaver->pWindow = NullWindow;
 | |
|         FreeResource(pSaver->wid, X11_RESTYPE_NONE);
 | |
|         if (pPriv) {
 | |
|             UninstallSaverColormap(pScreen);
 | |
|             pPriv->hasWindow = FALSE;
 | |
|             CheckScreenPrivate(pScreen);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (!pPriv || !(pAttr = pPriv->attr))
 | |
|         return FALSE;
 | |
| 
 | |
|     pPriv->installedMap = None;
 | |
| 
 | |
|     if (GrabInProgress && GrabInProgress != pAttr->client->index)
 | |
|         return FALSE;
 | |
| 
 | |
|     pWin = CreateWindow(pSaver->wid, pScreen->root,
 | |
|                         pAttr->x, pAttr->y, pAttr->width, pAttr->height,
 | |
|                         pAttr->borderWidth, pAttr->class,
 | |
|                         pAttr->mask, (XID *) pAttr->values,
 | |
|                         pAttr->depth, serverClient, pAttr->visual, &result);
 | |
|     if (!pWin)
 | |
|         return FALSE;
 | |
| 
 | |
|     if (!AddResource(pWin->drawable.id, X11_RESTYPE_WINDOW, pWin))
 | |
|         return FALSE;
 | |
| 
 | |
|     mask = 0;
 | |
|     if (pAttr->pBackgroundPixmap) {
 | |
|         pWin->backgroundState = BackgroundPixmap;
 | |
|         pWin->background.pixmap = pAttr->pBackgroundPixmap;
 | |
|         pAttr->pBackgroundPixmap->refcnt++;
 | |
|         mask |= CWBackPixmap;
 | |
|     }
 | |
|     if (pAttr->pBorderPixmap) {
 | |
|         pWin->borderIsPixel = FALSE;
 | |
|         pWin->border.pixmap = pAttr->pBorderPixmap;
 | |
|         pAttr->pBorderPixmap->refcnt++;
 | |
|         mask |= CWBorderPixmap;
 | |
|     }
 | |
|     if (pAttr->pCursor) {
 | |
|         CursorPtr cursor;
 | |
|         if (!pWin->optional)
 | |
|             if (!MakeWindowOptional(pWin)) {
 | |
|                 FreeResource(pWin->drawable.id, X11_RESTYPE_NONE);
 | |
|                 return FALSE;
 | |
|             }
 | |
|         cursor = RefCursor(pAttr->pCursor);
 | |
|         if (pWin->optional->cursor)
 | |
|             FreeCursor(pWin->optional->cursor, (Cursor) 0);
 | |
|         pWin->optional->cursor = cursor;
 | |
|         pWin->cursorIsNone = FALSE;
 | |
|         CheckWindowOptionalNeed(pWin);
 | |
|         mask |= CWCursor;
 | |
|     }
 | |
|     if (mask)
 | |
|         (*pScreen->ChangeWindowAttributes) (pWin, mask);
 | |
| 
 | |
|     if (pAttr->colormap != None)
 | |
|         (void) ChangeWindowAttributes(pWin, CWColormap, &pAttr->colormap,
 | |
|                                       serverClient);
 | |
| 
 | |
|     MapWindow(pWin, serverClient);
 | |
| 
 | |
|     pPriv->hasWindow = TRUE;
 | |
|     pSaver->pWindow = pWin;
 | |
| 
 | |
|     /* check and install our own colormap if it isn't installed now */
 | |
|     wantMap = wColormap(pWin);
 | |
|     if (wantMap == None || IsMapInstalled(wantMap, pWin))
 | |
|         return TRUE;
 | |
| 
 | |
|     result = dixLookupResourceByType((void **) &pCmap, wantMap, X11_RESTYPE_COLORMAP,
 | |
|                                      serverClient, DixInstallAccess);
 | |
|     if (result != Success)
 | |
|         return TRUE;
 | |
| 
 | |
|     pPriv->installedMap = wantMap;
 | |
| 
 | |
|     (*pCmap->pScreen->InstallColormap) (pCmap);
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| DestroySaverWindow(ScreenPtr pScreen)
 | |
| {
 | |
|     SetupScreen(pScreen);
 | |
|     ScreenSaverStuffPtr pSaver;
 | |
| 
 | |
|     if (!pPriv || !pPriv->hasWindow)
 | |
|         return FALSE;
 | |
| 
 | |
|     pSaver = &pScreen->screensaver;
 | |
|     if (pSaver->pWindow) {
 | |
|         pSaver->pWindow = NullWindow;
 | |
|         FreeResource(pSaver->wid, X11_RESTYPE_NONE);
 | |
|     }
 | |
|     pPriv->hasWindow = FALSE;
 | |
|     CheckScreenPrivate(pScreen);
 | |
|     UninstallSaverColormap(pScreen);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| ScreenSaverHandle(ScreenPtr pScreen, int xstate, Bool force)
 | |
| {
 | |
|     int state = 0;
 | |
|     Bool ret = FALSE;
 | |
|     ScreenSaverScreenPrivatePtr pPriv;
 | |
| 
 | |
|     switch (xstate) {
 | |
|     case SCREEN_SAVER_ON:
 | |
|         state = ScreenSaverOn;
 | |
|         ret = CreateSaverWindow(pScreen);
 | |
|         break;
 | |
|     case SCREEN_SAVER_OFF:
 | |
|         state = ScreenSaverOff;
 | |
|         ret = DestroySaverWindow(pScreen);
 | |
|         break;
 | |
|     case SCREEN_SAVER_CYCLE:
 | |
|         state = ScreenSaverCycle;
 | |
|         pPriv = GetScreenPrivate(pScreen);
 | |
|         if (pPriv && pPriv->hasWindow)
 | |
|             ret = TRUE;
 | |
| 
 | |
|     }
 | |
| #ifdef XINERAMA
 | |
|     if (noPanoramiXExtension || !pScreen->myNum)
 | |
| #endif /* XINERAMA */
 | |
|         SendScreenSaverNotify(pScreen, state, force);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcScreenSaverQueryVersion(ClientPtr client)
 | |
| {
 | |
|     xScreenSaverQueryVersionReply rep = {
 | |
|         .type = X_Reply,
 | |
|         .sequenceNumber = client->sequence,
 | |
|         .majorVersion = SERVER_SAVER_MAJOR_VERSION,
 | |
|         .minorVersion = SERVER_SAVER_MINOR_VERSION
 | |
|     };
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq);
 | |
| 
 | |
|     if (client->swapped) {
 | |
|         swaps(&rep.sequenceNumber);
 | |
|         swaps(&rep.majorVersion);
 | |
|         swaps(&rep.minorVersion);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xScreenSaverQueryVersionReply), &rep);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcScreenSaverQueryInfo(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xScreenSaverQueryInfoReq);
 | |
|     int rc;
 | |
|     ScreenSaverStuffPtr pSaver;
 | |
|     DrawablePtr pDraw;
 | |
|     CARD32 lastInput;
 | |
|     ScreenSaverScreenPrivatePtr pPriv;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq);
 | |
|     rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
 | |
|                            DixGetAttrAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
|     rc = XaceHookScreensaverAccess(client, pDraw->pScreen, DixGetAttrAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
| 
 | |
|     pSaver = &pDraw->pScreen->screensaver;
 | |
|     pPriv = GetScreenPrivate(pDraw->pScreen);
 | |
| 
 | |
|     UpdateCurrentTime();
 | |
|     lastInput = GetTimeInMillis() - LastEventTime(XIAllDevices).milliseconds;
 | |
| 
 | |
|     xScreenSaverQueryInfoReply rep = {
 | |
|         .type = X_Reply,
 | |
|         .sequenceNumber = client->sequence,
 | |
|         .window = pSaver->wid
 | |
|     };
 | |
|     if (screenIsSaved != SCREEN_SAVER_OFF) {
 | |
|         rep.state = ScreenSaverOn;
 | |
|         if (ScreenSaverTime)
 | |
|             rep.tilOrSince = lastInput - ScreenSaverTime;
 | |
|     }
 | |
|     else {
 | |
|         if (ScreenSaverTime) {
 | |
|             rep.state = ScreenSaverOff;
 | |
|             if (ScreenSaverTime >= lastInput)
 | |
|                 rep.tilOrSince = ScreenSaverTime - lastInput;
 | |
|         }
 | |
|         else {
 | |
|             rep.state = ScreenSaverDisabled;
 | |
|         }
 | |
|     }
 | |
|     rep.idle = lastInput;
 | |
|     rep.eventMask = getEventMask(pDraw->pScreen, client);
 | |
|     if (pPriv && pPriv->attr)
 | |
|         rep.kind = ScreenSaverExternal;
 | |
|     else if (ScreenSaverBlanking != DontPreferBlanking)
 | |
|         rep.kind = ScreenSaverBlanked;
 | |
|     else
 | |
|         rep.kind = ScreenSaverInternal;
 | |
|     if (client->swapped) {
 | |
|         swaps(&rep.sequenceNumber);
 | |
|         swapl(&rep.window);
 | |
|         swapl(&rep.tilOrSince);
 | |
|         swapl(&rep.idle);
 | |
|         swapl(&rep.eventMask);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xScreenSaverQueryInfoReply), &rep);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcScreenSaverSelectInput(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xScreenSaverSelectInputReq);
 | |
|     DrawablePtr pDraw;
 | |
|     int rc;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq);
 | |
|     rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
 | |
|                            DixGetAttrAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
| 
 | |
|     rc = XaceHookScreensaverAccess(client, pDraw->pScreen, DixSetAttrAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
| 
 | |
|     if (!setEventMask(pDraw->pScreen, client, stuff->eventMask))
 | |
|         return BadAlloc;
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ScreenSaverSetAttributes(ClientPtr client, xScreenSaverSetAttributesReq *stuff)
 | |
| {
 | |
|     DrawablePtr pDraw;
 | |
|     WindowPtr pParent;
 | |
|     ScreenPtr pScreen;
 | |
|     ScreenSaverScreenPrivatePtr pPriv = 0;
 | |
|     ScreenSaverAttrPtr pAttr = 0;
 | |
|     int ret, len, class, bw, depth;
 | |
|     unsigned long visual;
 | |
|     int idepth, ivisual;
 | |
|     Bool fOK;
 | |
|     DepthPtr pDepth;
 | |
|     WindowOptPtr ancwopt;
 | |
|     unsigned int *pVlist;
 | |
|     unsigned long *values = 0;
 | |
|     unsigned long tmask, imask;
 | |
|     unsigned long val;
 | |
|     Pixmap pixID;
 | |
|     PixmapPtr pPixmap;
 | |
|     Cursor cursorID;
 | |
|     CursorPtr pCursor;
 | |
|     Colormap cmap;
 | |
|     ColormapPtr pCmap;
 | |
| 
 | |
|     ret = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
 | |
|                             DixGetAttrAccess);
 | |
|     if (ret != Success)
 | |
|         return ret;
 | |
|     pScreen = pDraw->pScreen;
 | |
|     pParent = pScreen->root;
 | |
| 
 | |
|     ret = XaceHookScreensaverAccess(client, pScreen, DixSetAttrAccess);
 | |
|     if (ret != Success)
 | |
|         return ret;
 | |
| 
 | |
|     len = client->req_len - bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
 | |
|     if (Ones(stuff->mask) != len)
 | |
|         return BadLength;
 | |
|     if (!stuff->width || !stuff->height) {
 | |
|         client->errorValue = 0;
 | |
|         return BadValue;
 | |
|     }
 | |
|     switch (class = stuff->c_class) {
 | |
|     case CopyFromParent:
 | |
|     case InputOnly:
 | |
|     case InputOutput:
 | |
|         break;
 | |
|     default:
 | |
|         client->errorValue = class;
 | |
|         return BadValue;
 | |
|     }
 | |
|     bw = stuff->borderWidth;
 | |
|     depth = stuff->depth;
 | |
|     visual = stuff->visualID;
 | |
| 
 | |
|     /* copied directly from CreateWindow */
 | |
| 
 | |
|     if (class == CopyFromParent)
 | |
|         class = pParent->drawable.class;
 | |
| 
 | |
|     if ((class != InputOutput) && (class != InputOnly)) {
 | |
|         client->errorValue = class;
 | |
|         return BadValue;
 | |
|     }
 | |
| 
 | |
|     if ((class != InputOnly) && (pParent->drawable.class == InputOnly))
 | |
|         return BadMatch;
 | |
| 
 | |
|     if ((class == InputOnly) && ((bw != 0) || (depth != 0)))
 | |
|         return BadMatch;
 | |
| 
 | |
|     if ((class == InputOutput) && (depth == 0))
 | |
|         depth = pParent->drawable.depth;
 | |
|     ancwopt = pParent->optional;
 | |
|     if (!ancwopt)
 | |
|         ancwopt = FindWindowWithOptional(pParent)->optional;
 | |
|     if (visual == CopyFromParent)
 | |
|         visual = ancwopt->visual;
 | |
| 
 | |
|     /* Find out if the depth and visual are acceptable for this Screen */
 | |
|     if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) {
 | |
|         fOK = FALSE;
 | |
|         for (idepth = 0; idepth < pScreen->numDepths; idepth++) {
 | |
|             pDepth = (DepthPtr) &pScreen->allowedDepths[idepth];
 | |
|             if ((depth == pDepth->depth) || (depth == 0)) {
 | |
|                 for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) {
 | |
|                     if (visual == pDepth->vids[ivisual]) {
 | |
|                         fOK = TRUE;
 | |
|                         break;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         if (fOK == FALSE)
 | |
|             return BadMatch;
 | |
|     }
 | |
| 
 | |
|     if (((stuff->mask & (CWBorderPixmap | CWBorderPixel)) == 0) &&
 | |
|         (class != InputOnly) && (depth != pParent->drawable.depth)) {
 | |
|         return BadMatch;
 | |
|     }
 | |
| 
 | |
|     if (((stuff->mask & CWColormap) == 0) &&
 | |
|         (class != InputOnly) &&
 | |
|         ((visual != ancwopt->visual) || (ancwopt->colormap == None))) {
 | |
|         return BadMatch;
 | |
|     }
 | |
| 
 | |
|     /* end of errors from CreateWindow */
 | |
| 
 | |
|     pPriv = GetScreenPrivate(pScreen);
 | |
|     if (pPriv && pPriv->attr) {
 | |
|         if (pPriv->attr->client != client)
 | |
|             return BadAccess;
 | |
|     }
 | |
|     if (!pPriv) {
 | |
|         pPriv = MakeScreenPrivate(pScreen);
 | |
|         if (!pPriv)
 | |
|             return FALSE;
 | |
|     }
 | |
|     pAttr = calloc(1, sizeof(ScreenSaverAttrRec));
 | |
|     if (!pAttr) {
 | |
|         ret = BadAlloc;
 | |
|         goto bail;
 | |
|     }
 | |
|     /* over allocate for override redirect */
 | |
|     pAttr->values = values = xallocarray(len + 1, sizeof(unsigned long));
 | |
|     if (!values) {
 | |
|         ret = BadAlloc;
 | |
|         goto bail;
 | |
|     }
 | |
|     pAttr->screen = pScreen;
 | |
|     pAttr->client = client;
 | |
|     pAttr->x = stuff->x;
 | |
|     pAttr->y = stuff->y;
 | |
|     pAttr->width = stuff->width;
 | |
|     pAttr->height = stuff->height;
 | |
|     pAttr->borderWidth = stuff->borderWidth;
 | |
|     pAttr->class = stuff->c_class;
 | |
|     pAttr->depth = depth;
 | |
|     pAttr->visual = visual;
 | |
|     pAttr->colormap = None;
 | |
|     pAttr->pCursor = NullCursor;
 | |
|     pAttr->pBackgroundPixmap = NullPixmap;
 | |
|     pAttr->pBorderPixmap = NullPixmap;
 | |
|     /*
 | |
|      * go through the mask, checking the values,
 | |
|      * looking up pixmaps and cursors and hold a reference
 | |
|      * to them.
 | |
|      */
 | |
|     pAttr->mask = tmask = stuff->mask | CWOverrideRedirect;
 | |
|     pVlist = (unsigned int *) (stuff + 1);
 | |
|     while (tmask) {
 | |
|         imask = lowbit(tmask);
 | |
|         tmask &= ~imask;
 | |
|         switch (imask) {
 | |
|         case CWBackPixmap:
 | |
|             pixID = (Pixmap) * pVlist;
 | |
|             if (pixID == None) {
 | |
|                 *values++ = None;
 | |
|             }
 | |
|             else if (pixID == ParentRelative) {
 | |
|                 if (depth != pParent->drawable.depth) {
 | |
|                     ret = BadMatch;
 | |
|                     goto PatchUp;
 | |
|                 }
 | |
|                 *values++ = ParentRelative;
 | |
|             }
 | |
|             else {
 | |
|                 ret =
 | |
|                     dixLookupResourceByType((void **) &pPixmap, pixID,
 | |
|                                             X11_RESTYPE_PIXMAP, client, DixReadAccess);
 | |
|                 if (ret == Success) {
 | |
|                     if ((pPixmap->drawable.depth != depth) ||
 | |
|                         (pPixmap->drawable.pScreen != pScreen)) {
 | |
|                         ret = BadMatch;
 | |
|                         goto PatchUp;
 | |
|                     }
 | |
|                     pAttr->pBackgroundPixmap = pPixmap;
 | |
|                     pPixmap->refcnt++;
 | |
|                     pAttr->mask &= ~CWBackPixmap;
 | |
|                 }
 | |
|                 else {
 | |
|                     client->errorValue = pixID;
 | |
|                     goto PatchUp;
 | |
|                 }
 | |
|             }
 | |
|             break;
 | |
|         case CWBackPixel:
 | |
|             *values++ = (CARD32) *pVlist;
 | |
|             break;
 | |
|         case CWBorderPixmap:
 | |
|             pixID = (Pixmap) * pVlist;
 | |
|             if (pixID == CopyFromParent) {
 | |
|                 if (depth != pParent->drawable.depth) {
 | |
|                     ret = BadMatch;
 | |
|                     goto PatchUp;
 | |
|                 }
 | |
|                 *values++ = CopyFromParent;
 | |
|             }
 | |
|             else {
 | |
|                 ret =
 | |
|                     dixLookupResourceByType((void **) &pPixmap, pixID,
 | |
|                                             X11_RESTYPE_PIXMAP, client, DixReadAccess);
 | |
|                 if (ret == Success) {
 | |
|                     if ((pPixmap->drawable.depth != depth) ||
 | |
|                         (pPixmap->drawable.pScreen != pScreen)) {
 | |
|                         ret = BadMatch;
 | |
|                         goto PatchUp;
 | |
|                     }
 | |
|                     pAttr->pBorderPixmap = pPixmap;
 | |
|                     pPixmap->refcnt++;
 | |
|                     pAttr->mask &= ~CWBorderPixmap;
 | |
|                 }
 | |
|                 else {
 | |
|                     client->errorValue = pixID;
 | |
|                     goto PatchUp;
 | |
|                 }
 | |
|             }
 | |
|             break;
 | |
|         case CWBorderPixel:
 | |
|             *values++ = (CARD32) *pVlist;
 | |
|             break;
 | |
|         case CWBitGravity:
 | |
|             val = (CARD8) *pVlist;
 | |
|             if (val > StaticGravity) {
 | |
|                 ret = BadValue;
 | |
|                 client->errorValue = val;
 | |
|                 goto PatchUp;
 | |
|             }
 | |
|             *values++ = val;
 | |
|             break;
 | |
|         case CWWinGravity:
 | |
|             val = (CARD8) *pVlist;
 | |
|             if (val > StaticGravity) {
 | |
|                 ret = BadValue;
 | |
|                 client->errorValue = val;
 | |
|                 goto PatchUp;
 | |
|             }
 | |
|             *values++ = val;
 | |
|             break;
 | |
|         case CWBackingStore:
 | |
|             val = (CARD8) *pVlist;
 | |
|             if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) {
 | |
|                 ret = BadValue;
 | |
|                 client->errorValue = val;
 | |
|                 goto PatchUp;
 | |
|             }
 | |
|             *values++ = val;
 | |
|             break;
 | |
|         case CWBackingPlanes:
 | |
|             *values++ = (CARD32) *pVlist;
 | |
|             break;
 | |
|         case CWBackingPixel:
 | |
|             *values++ = (CARD32) *pVlist;
 | |
|             break;
 | |
|         case CWSaveUnder:
 | |
|             val = (BOOL) * pVlist;
 | |
|             if ((val != xTrue) && (val != xFalse)) {
 | |
|                 ret = BadValue;
 | |
|                 client->errorValue = val;
 | |
|                 goto PatchUp;
 | |
|             }
 | |
|             *values++ = val;
 | |
|             break;
 | |
|         case CWEventMask:
 | |
|             *values++ = (CARD32) *pVlist;
 | |
|             break;
 | |
|         case CWDontPropagate:
 | |
|             *values++ = (CARD32) *pVlist;
 | |
|             break;
 | |
|         case CWOverrideRedirect:
 | |
|             if (!(stuff->mask & CWOverrideRedirect))
 | |
|                 pVlist--;
 | |
|             else {
 | |
|                 val = (BOOL) * pVlist;
 | |
|                 if ((val != xTrue) && (val != xFalse)) {
 | |
|                     ret = BadValue;
 | |
|                     client->errorValue = val;
 | |
|                     goto PatchUp;
 | |
|                 }
 | |
|             }
 | |
|             *values++ = xTrue;
 | |
|             break;
 | |
|         case CWColormap:
 | |
|             cmap = (Colormap) * pVlist;
 | |
|             ret = dixLookupResourceByType((void **) &pCmap, cmap, X11_RESTYPE_COLORMAP,
 | |
|                                           client, DixUseAccess);
 | |
|             if (ret != Success) {
 | |
|                 client->errorValue = cmap;
 | |
|                 goto PatchUp;
 | |
|             }
 | |
|             if (pCmap->pVisual->vid != visual || pCmap->pScreen != pScreen) {
 | |
|                 ret = BadMatch;
 | |
|                 goto PatchUp;
 | |
|             }
 | |
|             pAttr->colormap = cmap;
 | |
|             pAttr->mask &= ~CWColormap;
 | |
|             break;
 | |
|         case CWCursor:
 | |
|             cursorID = (Cursor) * pVlist;
 | |
|             if (cursorID == None) {
 | |
|                 *values++ = None;
 | |
|             }
 | |
|             else {
 | |
|                 ret = dixLookupResourceByType((void **) &pCursor, cursorID,
 | |
|                                               X11_RESTYPE_CURSOR, client, DixUseAccess);
 | |
|                 if (ret != Success) {
 | |
|                     client->errorValue = cursorID;
 | |
|                     goto PatchUp;
 | |
|                 }
 | |
|                 pAttr->pCursor = RefCursor(pCursor);
 | |
|                 pAttr->mask &= ~CWCursor;
 | |
|             }
 | |
|             break;
 | |
|         default:
 | |
|             ret = BadValue;
 | |
|             client->errorValue = stuff->mask;
 | |
|             goto PatchUp;
 | |
|         }
 | |
|         pVlist++;
 | |
|     }
 | |
|     if (pPriv->attr)
 | |
|         FreeResource(pPriv->attr->resource, AttrType);
 | |
|     pPriv->attr = pAttr;
 | |
|     pAttr->resource = FakeClientID(client->index);
 | |
|     if (!AddResource(pAttr->resource, AttrType, (void *) pAttr))
 | |
|         return BadAlloc;
 | |
|     return Success;
 | |
|  PatchUp:
 | |
|     FreeAttrs(pAttr);
 | |
|  bail:
 | |
|     CheckScreenPrivate(pScreen);
 | |
|     if (pAttr)
 | |
|         free(pAttr->values);
 | |
|     free(pAttr);
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ScreenSaverUnsetAttributes(ClientPtr client, Drawable drawable)
 | |
| {
 | |
|     DrawablePtr pDraw;
 | |
|     ScreenSaverScreenPrivatePtr pPriv;
 | |
|     int rc;
 | |
| 
 | |
|     rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixGetAttrAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
|     pPriv = GetScreenPrivate(pDraw->pScreen);
 | |
|     if (pPriv && pPriv->attr && pPriv->attr->client == client) {
 | |
|         FreeResource(pPriv->attr->resource, AttrType);
 | |
|         FreeScreenAttr(pPriv->attr);
 | |
|         pPriv->attr = NULL;
 | |
|         CheckScreenPrivate(pDraw->pScreen);
 | |
|     }
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcScreenSaverSetAttributes(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xScreenSaverSetAttributesReq);
 | |
|     REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq);
 | |
| 
 | |
| #ifdef XINERAMA
 | |
|     if (!noPanoramiXExtension) {
 | |
|         PanoramiXRes *draw;
 | |
|         PanoramiXRes *backPix = NULL;
 | |
|         PanoramiXRes *bordPix = NULL;
 | |
|         PanoramiXRes *cmap = NULL;
 | |
|         int i, status, len;
 | |
|         int pback_offset = 0, pbord_offset = 0, cmap_offset = 0;
 | |
|         XID orig_visual, tmp;
 | |
| 
 | |
|         status = dixLookupResourceByClass((void **) &draw, stuff->drawable,
 | |
|                                           XRC_DRAWABLE, client, DixWriteAccess);
 | |
|         if (status != Success)
 | |
|             return (status == BadValue) ? BadDrawable : status;
 | |
| 
 | |
|         len =
 | |
|             client->req_len -
 | |
|             bytes_to_int32(sizeof(xScreenSaverSetAttributesReq));
 | |
|         if (Ones(stuff->mask) != len)
 | |
|             return BadLength;
 | |
| 
 | |
|         if ((Mask) stuff->mask & CWBackPixmap) {
 | |
|             pback_offset = Ones((Mask) stuff->mask & (CWBackPixmap - 1));
 | |
|             tmp = *((CARD32 *) &stuff[1] + pback_offset);
 | |
|             if ((tmp != None) && (tmp != ParentRelative)) {
 | |
|                 status = dixLookupResourceByType((void **) &backPix, tmp,
 | |
|                                                  XRT_PIXMAP, client,
 | |
|                                                  DixReadAccess);
 | |
|                 if (status != Success)
 | |
|                     return status;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if ((Mask) stuff->mask & CWBorderPixmap) {
 | |
|             pbord_offset = Ones((Mask) stuff->mask & (CWBorderPixmap - 1));
 | |
|             tmp = *((CARD32 *) &stuff[1] + pbord_offset);
 | |
|             if (tmp != CopyFromParent) {
 | |
|                 status = dixLookupResourceByType((void **) &bordPix, tmp,
 | |
|                                                  XRT_PIXMAP, client,
 | |
|                                                  DixReadAccess);
 | |
|                 if (status != Success)
 | |
|                     return status;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if ((Mask) stuff->mask & CWColormap) {
 | |
|             cmap_offset = Ones((Mask) stuff->mask & (CWColormap - 1));
 | |
|             tmp = *((CARD32 *) &stuff[1] + cmap_offset);
 | |
|             if (tmp != CopyFromParent) {
 | |
|                 status = dixLookupResourceByType((void **) &cmap, tmp,
 | |
|                                                  XRT_COLORMAP, client,
 | |
|                                                  DixReadAccess);
 | |
|                 if (status != Success)
 | |
|                     return status;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         orig_visual = stuff->visualID;
 | |
| 
 | |
|         FOR_NSCREENS_BACKWARD(i) {
 | |
|             stuff->drawable = draw->info[i].id;
 | |
|             if (backPix)
 | |
|                 *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[i].id;
 | |
|             if (bordPix)
 | |
|                 *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[i].id;
 | |
|             if (cmap)
 | |
|                 *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[i].id;
 | |
| 
 | |
|             if (orig_visual != CopyFromParent)
 | |
|                 stuff->visualID = PanoramiXTranslateVisualID(i, orig_visual);
 | |
| 
 | |
|             status = ScreenSaverSetAttributes(client, stuff);
 | |
|         }
 | |
| 
 | |
|         return status;
 | |
|     }
 | |
| #endif /* XINERAMA */
 | |
| 
 | |
|     return ScreenSaverSetAttributes(client, stuff);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcScreenSaverUnsetAttributes(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xScreenSaverUnsetAttributesReq);
 | |
|     REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq);
 | |
| 
 | |
| #ifdef XINERAMA
 | |
|     if (!noPanoramiXExtension) {
 | |
|         PanoramiXRes *draw;
 | |
|         int rc, i;
 | |
| 
 | |
| 
 | |
|         rc = dixLookupResourceByClass((void **) &draw, stuff->drawable,
 | |
|                                       XRC_DRAWABLE, client, DixWriteAccess);
 | |
|         if (rc != Success)
 | |
|             return (rc == BadValue) ? BadDrawable : rc;
 | |
| 
 | |
|         for (i = PanoramiXNumScreens - 1; i > 0; i--) {
 | |
|             ScreenSaverUnsetAttributes(client, draw->info[i].id);
 | |
|         }
 | |
| 
 | |
|         stuff->drawable = draw->info[0].id;
 | |
|     }
 | |
| #endif /* XINERAMA */
 | |
| 
 | |
|     return ScreenSaverUnsetAttributes(client, stuff->drawable);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcScreenSaverSuspend(ClientPtr client)
 | |
| {
 | |
|     ScreenSaverSuspensionPtr *prev, this;
 | |
|     BOOL suspend;
 | |
| 
 | |
|     REQUEST(xScreenSaverSuspendReq);
 | |
|     REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
 | |
| 
 | |
|     /*
 | |
|      * Old versions of XCB encode suspend as 1 byte followed by three
 | |
|      * pad bytes (which are always cleared), instead of a 4 byte
 | |
|      * value. Be compatible by just checking for a non-zero value in
 | |
|      * all 32-bits.
 | |
|      */
 | |
|     suspend = stuff->suspend != 0;
 | |
| 
 | |
|     /* Check if this client is suspending the screensaver */
 | |
|     for (prev = &suspendingClients; (this = *prev); prev = &this->next)
 | |
|         if (this->pClient == client)
 | |
|             break;
 | |
| 
 | |
|     if (this) {
 | |
|         if (suspend == TRUE)
 | |
|             this->count++;
 | |
|         else if (--this->count == 0)
 | |
|             FreeResource(this->clientResource, X11_RESTYPE_NONE);
 | |
| 
 | |
|         return Success;
 | |
|     }
 | |
| 
 | |
|     /* If we get to this point, this client isn't suspending the screensaver */
 | |
|     if (suspend == FALSE)
 | |
|         return Success;
 | |
| 
 | |
|     /*
 | |
|      * Allocate a suspension record for the client, and stop the screensaver
 | |
|      * if it isn't already suspended by another client. We attach a resource ID
 | |
|      * to the record, so the screensaver will be re-enabled and the record freed
 | |
|      * if the client disconnects without reenabling it first.
 | |
|      */
 | |
|     this = malloc(sizeof(ScreenSaverSuspensionRec));
 | |
| 
 | |
|     if (!this)
 | |
|         return BadAlloc;
 | |
| 
 | |
|     this->next = NULL;
 | |
|     this->pClient = client;
 | |
|     this->count = 1;
 | |
|     this->clientResource = FakeClientID(client->index);
 | |
| 
 | |
|     if (!AddResource(this->clientResource, SuspendType, (void *) this)) {
 | |
|         free(this);
 | |
|         return BadAlloc;
 | |
|     }
 | |
| 
 | |
|     *prev = this;
 | |
|     if (!screenSaverSuspended) {
 | |
|         screenSaverSuspended = TRUE;
 | |
|         FreeScreenSaverTimer();
 | |
|     }
 | |
| 
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcScreenSaverDispatch(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xReq);
 | |
|     switch (stuff->data) {
 | |
|         case X_ScreenSaverQueryVersion:
 | |
|             return ProcScreenSaverQueryVersion(client);
 | |
|         case X_ScreenSaverQueryInfo:
 | |
|             return ProcScreenSaverQueryInfo(client);
 | |
|         case X_ScreenSaverSelectInput:
 | |
|             return ProcScreenSaverSelectInput(client);
 | |
|         case X_ScreenSaverSetAttributes:
 | |
|             return ProcScreenSaverSetAttributes(client);
 | |
|         case X_ScreenSaverUnsetAttributes:
 | |
|             return ProcScreenSaverUnsetAttributes(client);
 | |
|         case X_ScreenSaverSuspend:
 | |
|             return ProcScreenSaverSuspend(client);
 | |
|         default:
 | |
|             return BadRequest;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static int _X_COLD
 | |
| SProcScreenSaverQueryInfo(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xScreenSaverQueryInfoReq);
 | |
|     REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq);
 | |
|     swapl(&stuff->drawable);
 | |
|     return ProcScreenSaverQueryInfo(client);
 | |
| }
 | |
| 
 | |
| static int _X_COLD
 | |
| SProcScreenSaverSelectInput(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xScreenSaverSelectInputReq);
 | |
|     REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq);
 | |
|     swapl(&stuff->drawable);
 | |
|     swapl(&stuff->eventMask);
 | |
|     return ProcScreenSaverSelectInput(client);
 | |
| }
 | |
| 
 | |
| static int _X_COLD
 | |
| SProcScreenSaverSetAttributes(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xScreenSaverSetAttributesReq);
 | |
|     REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq);
 | |
|     swapl(&stuff->drawable);
 | |
|     swaps(&stuff->x);
 | |
|     swaps(&stuff->y);
 | |
|     swaps(&stuff->width);
 | |
|     swaps(&stuff->height);
 | |
|     swaps(&stuff->borderWidth);
 | |
|     swapl(&stuff->visualID);
 | |
|     swapl(&stuff->mask);
 | |
|     SwapRestL(stuff);
 | |
|     return ProcScreenSaverSetAttributes(client);
 | |
| }
 | |
| 
 | |
| static int _X_COLD
 | |
| SProcScreenSaverUnsetAttributes(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xScreenSaverUnsetAttributesReq);
 | |
|     REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq);
 | |
|     swapl(&stuff->drawable);
 | |
|     return ProcScreenSaverUnsetAttributes(client);
 | |
| }
 | |
| 
 | |
| static int _X_COLD
 | |
| SProcScreenSaverSuspend(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xScreenSaverSuspendReq);
 | |
|     REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
 | |
|     swapl(&stuff->suspend);
 | |
|     return ProcScreenSaverSuspend(client);
 | |
| }
 | |
| 
 | |
| static int _X_COLD
 | |
| SProcScreenSaverDispatch(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xReq);
 | |
|     switch (stuff->data) {
 | |
|         case X_ScreenSaverQueryVersion:
 | |
|             return ProcScreenSaverQueryVersion(client);
 | |
|         case X_ScreenSaverQueryInfo:
 | |
|             return SProcScreenSaverQueryInfo(client);
 | |
|         case X_ScreenSaverSelectInput:
 | |
|             return SProcScreenSaverSelectInput(client);
 | |
|         case X_ScreenSaverSetAttributes:
 | |
|             return SProcScreenSaverSetAttributes(client);
 | |
|         case X_ScreenSaverUnsetAttributes:
 | |
|             return SProcScreenSaverUnsetAttributes(client);
 | |
|         case X_ScreenSaverSuspend:
 | |
|             return SProcScreenSaverSuspend(client);
 | |
|         default:
 | |
|             return BadRequest;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| ScreenSaverExtensionInit(void)
 | |
| {
 | |
|     ExtensionEntry *extEntry;
 | |
|     int i;
 | |
|     ScreenPtr pScreen;
 | |
| 
 | |
|     if (!dixRegisterPrivateKey(&ScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
 | |
|         return;
 | |
| 
 | |
|     AttrType = CreateNewResourceType(ScreenSaverFreeAttr, "SaverAttr");
 | |
|     SaverEventType = CreateNewResourceType(ScreenSaverFreeEvents, "SaverEvent");
 | |
|     SuspendType = CreateNewResourceType(ScreenSaverFreeSuspend, "SaverSuspend");
 | |
| 
 | |
|     for (i = 0; i < screenInfo.numScreens; i++) {
 | |
|         pScreen = screenInfo.screens[i];
 | |
|         SetScreenPrivate(pScreen, NULL);
 | |
|     }
 | |
|     if (AttrType && SaverEventType && SuspendType &&
 | |
|         (extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0,
 | |
|                                  ProcScreenSaverDispatch,
 | |
|                                  SProcScreenSaverDispatch, NULL,
 | |
|                                  StandardMinorOpcode))) {
 | |
|         ScreenSaverEventBase = extEntry->eventBase;
 | |
|         EventSwapVector[ScreenSaverEventBase] =
 | |
|             (EventSwapPtr) SScreenSaverNotifyEvent;
 | |
|     }
 | |
| }
 |