Home | History | Annotate | Line # | Download | only in dmx
      1 /*
      2  * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
      3  *
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining
      7  * a copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation on the rights to use, copy, modify, merge,
     10  * publish, distribute, sublicense, and/or sell copies of the Software,
     11  * and to permit persons to whom the Software is furnished to do so,
     12  * subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial
     16  * portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     21  * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
     22  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     23  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     25  * SOFTWARE.
     26  */
     27 
     28 /*
     29  * Authors:
     30  *   Kevin E. Martin <kem (at) redhat.com>
     31  *   David H. Dawes <dawes (at) xfree86.org>
     32  *
     33  */
     34 
     35 /** \file
     36  * This file provides support for screen initialization. */
     37 
     38 #ifdef HAVE_DMX_CONFIG_H
     39 #include <dmx-config.h>
     40 #endif
     41 
     42 #include "dmx.h"
     43 #include "dmxsync.h"
     44 #include "dmxshadow.h"
     45 #include "dmxscrinit.h"
     46 #include "dmxcursor.h"
     47 #include "dmxgc.h"
     48 #include "dmxgcops.h"
     49 #include "dmxwindow.h"
     50 #include "dmxpixmap.h"
     51 #include "dmxfont.h"
     52 #include "dmxcmap.h"
     53 #include "dmxprop.h"
     54 #include "dmxdpms.h"
     55 
     56 #include "dmxpict.h"
     57 
     58 #include "fb.h"
     59 #include "mipointer.h"
     60 #include "micmap.h"
     61 
     62 extern Bool dmxCloseScreen(int idx, ScreenPtr pScreen);
     63 static Bool dmxSaveScreen(ScreenPtr pScreen, int what);
     64 
     65 static unsigned long dmxGeneration;
     66 static unsigned long *dmxCursorGeneration;
     67 
     68 DevPrivateKeyRec dmxGCPrivateKeyRec;
     69 DevPrivateKeyRec dmxWinPrivateKeyRec;
     70 DevPrivateKeyRec dmxPixPrivateKeyRec;
     71 int dmxFontPrivateIndex;        /**< Private index for Fonts     */
     72 DevPrivateKeyRec dmxScreenPrivateKeyRec;
     73 DevPrivateKeyRec dmxColormapPrivateKeyRec;
     74 DevPrivateKeyRec dmxPictPrivateKeyRec;
     75 DevPrivateKeyRec dmxGlyphSetPrivateKeyRec;
     76 
     77 /** Initialize the parts of screen \a idx that require access to the
     78  *  back-end server. */
     79 void dmxBEScreenInit(int idx, ScreenPtr pScreen)
     80 {
     81     DMXScreenInfo        *dmxScreen = &dmxScreens[idx];
     82     XSetWindowAttributes  attribs;
     83     XGCValues             gcvals;
     84     unsigned long         mask;
     85     int                   i, j;
     86 
     87     /* FIXME: The dmxScreenInit() code currently assumes that it will
     88      * not be called if the Xdmx server is started with this screen
     89      * detached -- i.e., it assumes that dmxScreen->beDisplay is always
     90      * valid.  This is not necessarily a valid assumption when full
     91      * addition/removal of screens is implemented, but when this code is
     92      * broken out for screen reattachment, then we will reevaluate this
     93      * assumption.
     94      */
     95 
     96     pScreen->mmWidth = DisplayWidthMM(dmxScreen->beDisplay,
     97 				      DefaultScreen(dmxScreen->beDisplay));
     98     pScreen->mmHeight = DisplayHeightMM(dmxScreen->beDisplay,
     99 					DefaultScreen(dmxScreen->beDisplay));
    100 
    101     pScreen->whitePixel = dmxScreen->beWhitePixel;
    102     pScreen->blackPixel = dmxScreen->beBlackPixel;
    103 
    104     /* Handle screen savers and DPMS on the backend */
    105     dmxDPMSInit(dmxScreen);
    106 
    107     /* Create root window for screen */
    108     mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect;
    109     attribs.background_pixel = dmxScreen->beBlackPixel;
    110     attribs.event_mask = (KeyPressMask
    111                           | KeyReleaseMask
    112                           | ButtonPressMask
    113                           | ButtonReleaseMask
    114                           | EnterWindowMask
    115                           | LeaveWindowMask
    116                           | PointerMotionMask
    117                           | KeymapStateMask
    118                           | FocusChangeMask);
    119     attribs.colormap = dmxScreen->beDefColormaps[dmxScreen->beDefVisualIndex];
    120     attribs.override_redirect = True;
    121 
    122     dmxScreen->scrnWin =
    123 	XCreateWindow(dmxScreen->beDisplay,
    124 		      DefaultRootWindow(dmxScreen->beDisplay),
    125 		      dmxScreen->scrnX,
    126 		      dmxScreen->scrnY,
    127 		      dmxScreen->scrnWidth,
    128 		      dmxScreen->scrnHeight,
    129 		      0,
    130 		      pScreen->rootDepth,
    131 		      InputOutput,
    132 		      dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
    133 		      mask,
    134 		      &attribs);
    135     dmxPropertyWindow(dmxScreen);
    136 
    137     /*
    138      * This turns off the cursor by defining a cursor with no visible
    139      * components.
    140      */
    141     {
    142 	char noCursorData[] = {0, 0, 0, 0,
    143 			       0, 0, 0, 0};
    144 	Pixmap pixmap;
    145 	XColor color, tmp;
    146 
    147 	pixmap = XCreateBitmapFromData(dmxScreen->beDisplay, dmxScreen->scrnWin,
    148 				       noCursorData, 8, 8);
    149 	XAllocNamedColor(dmxScreen->beDisplay, dmxScreen->beDefColormaps[0],
    150 			 "black", &color, &tmp);
    151 	dmxScreen->noCursor = XCreatePixmapCursor(dmxScreen->beDisplay,
    152 						  pixmap, pixmap,
    153 						  &color, &color, 0, 0);
    154 	XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin,
    155 		      dmxScreen->noCursor);
    156 
    157 	XFreePixmap(dmxScreen->beDisplay, pixmap);
    158     }
    159 
    160     XMapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
    161 
    162     if (dmxShadowFB) {
    163 	mask = (GCFunction
    164 		| GCPlaneMask
    165 		| GCClipMask);
    166 	gcvals.function = GXcopy;
    167 	gcvals.plane_mask = AllPlanes;
    168 	gcvals.clip_mask = None;
    169 
    170 	dmxScreen->shadowGC = XCreateGC(dmxScreen->beDisplay,
    171 					dmxScreen->scrnWin,
    172 					mask, &gcvals);
    173 
    174 	dmxScreen->shadowFBImage =
    175 	    XCreateImage(dmxScreen->beDisplay,
    176 			 dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
    177 			 dmxScreen->beDepth,
    178 			 ZPixmap,
    179 			 0,
    180 			 (char *)dmxScreen->shadow,
    181 			 dmxScreen->scrnWidth, dmxScreen->scrnHeight,
    182 			 dmxScreen->beBPP,
    183 			 PixmapBytePad(dmxScreen->scrnWidth,
    184 				       dmxScreen->beBPP));
    185     } else {
    186 	/* Create default drawables (used during GC creation) */
    187 	for (i = 0; i < dmxScreen->beNumPixmapFormats; i++)
    188 	    for (j = 0; j < dmxScreen->beNumDepths; j++)
    189 		if ((dmxScreen->bePixmapFormats[i].depth == 1) ||
    190 		    (dmxScreen->bePixmapFormats[i].depth ==
    191 		     dmxScreen->beDepths[j])) {
    192 		    dmxScreen->scrnDefDrawables[i] = (Drawable)
    193 			XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
    194 				      1, 1, dmxScreen->bePixmapFormats[i].depth);
    195 		    break;
    196 		}
    197     }
    198 }
    199 
    200 /** Initialize screen number \a idx. */
    201 Bool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[])
    202 {
    203     DMXScreenInfo        *dmxScreen = &dmxScreens[idx];
    204     int                   i, j;
    205 
    206     if (!dixRegisterPrivateKey(&dmxScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
    207 	return FALSE;
    208     if (!dixRegisterPrivateKey(&dmxColormapPrivateKeyRec, PRIVATE_COLORMAP, 0))
    209 	return FALSE;
    210     if (!dixRegisterPrivateKey(&dmxGlyphSetPrivateKeyRec, PRIVATE_GLYPHSET, 0))
    211 	return FALSE;
    212 
    213     if (dmxGeneration != serverGeneration) {
    214 	/* Allocate font private index */
    215 	dmxFontPrivateIndex = AllocateFontPrivateIndex();
    216 	if (dmxFontPrivateIndex == -1)
    217 	    return FALSE;
    218 
    219 	dmxGeneration = serverGeneration;
    220     }
    221 
    222     if (dmxShadowFB) {
    223 	dmxScreen->shadow = shadowAlloc(dmxScreen->scrnWidth,
    224 					dmxScreen->scrnHeight,
    225 					dmxScreen->beBPP);
    226     } else {
    227 	if (!dmxInitGC(pScreen)) return FALSE;
    228 	if (!dmxInitWindow(pScreen)) return FALSE;
    229 	if (!dmxInitPixmap(pScreen)) return FALSE;
    230     }
    231 
    232     /*
    233      * Initalise the visual types.  miSetVisualTypesAndMasks() requires
    234      * that all of the types for each depth be collected together.  It's
    235      * intended for slightly different usage to what we would like here.
    236      * Maybe a miAddVisualTypeAndMask() function will be added to make
    237      * things easier here.
    238      */
    239     for (i = 0; i < dmxScreen->beNumDepths; i++) {
    240 	int    depth;
    241 	int    visuals        = 0;
    242 	int    bitsPerRgb     = 0;
    243 	int    preferredClass = -1;
    244 	Pixel  redMask        = 0;
    245 	Pixel  greenMask      = 0;
    246 	Pixel  blueMask       = 0;
    247 
    248 	depth = dmxScreen->beDepths[i];
    249 	for (j = 0; j < dmxScreen->beNumVisuals; j++) {
    250 	    XVisualInfo *vi;
    251 
    252 	    vi = &dmxScreen->beVisuals[j];
    253 	    if (vi->depth == depth) {
    254 		/* Assume the masks are all the same. */
    255 		visuals |= (1 << vi->class);
    256 		bitsPerRgb = vi->bits_per_rgb;
    257 		redMask = vi->red_mask;
    258 		greenMask = vi->green_mask;
    259 		blueMask = vi->blue_mask;
    260 		if (j == dmxScreen->beDefVisualIndex) {
    261 		    preferredClass = vi->class;
    262 		}
    263 	    }
    264 	}
    265 	miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb, preferredClass,
    266 				 redMask, greenMask, blueMask);
    267     }
    268 
    269     fbScreenInit(pScreen,
    270 		 dmxShadowFB ? dmxScreen->shadow : NULL,
    271 		 dmxScreen->scrnWidth,
    272 		 dmxScreen->scrnHeight,
    273 		 dmxScreen->beXDPI,
    274 		 dmxScreen->beXDPI,
    275 		 dmxScreen->scrnWidth,
    276 		 dmxScreen->beBPP);
    277     (void)dmxPictureInit(pScreen, 0, 0);
    278 
    279     /* Not yet... */
    280     pScreen->GetWindowPixmap = NULL;
    281     pScreen->SetWindowPixmap = NULL;
    282 
    283     if (dmxShadowFB && !shadowInit(pScreen, dmxShadowUpdateProc, NULL))
    284 	return FALSE;
    285 
    286     if (dmxShadowFB) {
    287 	miDCInitialize(pScreen, &dmxPointerCursorFuncs);
    288     } else {
    289         MAXSCREENSALLOC(dmxCursorGeneration);
    290 	if (dmxCursorGeneration[idx] != serverGeneration) {
    291 	    if (!(miPointerInitialize(pScreen,
    292 				      &dmxPointerSpriteFuncs,
    293 				      &dmxPointerCursorFuncs,
    294 				      FALSE)))
    295 		return FALSE;
    296 
    297 	    dmxCursorGeneration[idx] = serverGeneration;
    298 	}
    299     }
    300 
    301     DMX_WRAP(CloseScreen, dmxCloseScreen, dmxScreen, pScreen);
    302     DMX_WRAP(SaveScreen, dmxSaveScreen, dmxScreen, pScreen);
    303 
    304     dmxBEScreenInit(idx, pScreen);
    305 
    306     if (!dmxShadowFB) {
    307 	/* Wrap GC functions */
    308 	DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen);
    309 
    310 	/* Wrap Window functions */
    311 	DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen);
    312 	DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
    313 	DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen);
    314 	DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
    315 		 pScreen);
    316 	DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
    317 	DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
    318 	DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
    319 	DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen);
    320 	DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
    321 
    322 	DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
    323 	DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
    324 
    325 	DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
    326 
    327 	/* Wrap Image functions */
    328 	DMX_WRAP(GetImage, dmxGetImage, dmxScreen, pScreen);
    329 	DMX_WRAP(GetSpans, dmxGetSpans, dmxScreen, pScreen);
    330 
    331 	/* Wrap Pixmap functions */
    332 	DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen);
    333 	DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen);
    334 	DMX_WRAP(BitmapToRegion, dmxBitmapToRegion, dmxScreen, pScreen);
    335 
    336 	/* Wrap Font functions */
    337 	DMX_WRAP(RealizeFont, dmxRealizeFont, dmxScreen, pScreen);
    338 	DMX_WRAP(UnrealizeFont, dmxUnrealizeFont, dmxScreen, pScreen);
    339 
    340 	/* Wrap Colormap functions */
    341 	DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen);
    342 	DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen);
    343 	DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen);
    344 	DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen);
    345 
    346 	/* Wrap Shape functions */
    347 	DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
    348     }
    349 
    350     if (!dmxCreateDefColormap(pScreen))
    351 	return FALSE;
    352 
    353     return TRUE;
    354 }
    355 
    356 /** Close the \a pScreen resources on the back-end server. */
    357 void dmxBECloseScreen(ScreenPtr pScreen)
    358 {
    359     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
    360     int            i;
    361 
    362     /* Restore the back-end screen-saver and DPMS state. */
    363     dmxDPMSTerm(dmxScreen);
    364 
    365     /* Free the screen resources */
    366 
    367     XFreeCursor(dmxScreen->beDisplay, dmxScreen->noCursor);
    368     dmxScreen->noCursor = (Cursor)0;
    369 
    370     XUnmapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
    371     XDestroyWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
    372     dmxScreen->scrnWin = (Window)0;
    373 
    374     if (dmxShadowFB) {
    375 	/* Free the shadow GC and image assocated with the back-end server */
    376 	XFreeGC(dmxScreen->beDisplay, dmxScreen->shadowGC);
    377 	dmxScreen->shadowGC = NULL;
    378 	XFree(dmxScreen->shadowFBImage);
    379 	dmxScreen->shadowFBImage = NULL;
    380     } else {
    381 	/* Free the default drawables */
    382 	for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
    383 	    if (dmxScreen->scrnDefDrawables[i]) {
    384 		XFreePixmap(dmxScreen->beDisplay,
    385 			    dmxScreen->scrnDefDrawables[i]);
    386 		dmxScreen->scrnDefDrawables[i] = (Drawable)0;
    387 	    }
    388 	}
    389     }
    390 
    391     /* Free resources allocated during initialization (in dmxinit.c) */
    392     for (i = 0; i < dmxScreen->beNumDefColormaps; i++)
    393 	XFreeColormap(dmxScreen->beDisplay, dmxScreen->beDefColormaps[i]);
    394     free(dmxScreen->beDefColormaps);
    395     dmxScreen->beDefColormaps = NULL;
    396 
    397 #if 0
    398     /* Do not free visuals, depths and pixmap formats here.  Free them
    399      * in dmxCloseScreen() instead -- see comment below. */
    400     XFree(dmxScreen->beVisuals);
    401     dmxScreen->beVisuals = NULL;
    402 
    403     XFree(dmxScreen->beDepths);
    404     dmxScreen->beDepths = NULL;
    405 
    406     XFree(dmxScreen->bePixmapFormats);
    407     dmxScreen->bePixmapFormats = NULL;
    408 #endif
    409 
    410 #ifdef GLXEXT
    411     if (dmxScreen->glxVisuals) {
    412 	XFree(dmxScreen->glxVisuals);
    413 	dmxScreen->glxVisuals = NULL;
    414 	dmxScreen->numGlxVisuals = 0;
    415     }
    416 #endif
    417 
    418     /* Close display */
    419     XCloseDisplay(dmxScreen->beDisplay);
    420     dmxScreen->beDisplay = NULL;
    421 }
    422 
    423 /** Close screen number \a idx. */
    424 Bool dmxCloseScreen(int idx, ScreenPtr pScreen)
    425 {
    426     DMXScreenInfo *dmxScreen = &dmxScreens[idx];
    427 
    428     /* Reset the proc vectors */
    429     if (idx == 0) {
    430 	dmxResetRender();
    431 	dmxResetFonts();
    432     }
    433 
    434     if (dmxShadowFB) {
    435 	/* Free the shadow framebuffer */
    436 	free(dmxScreen->shadow);
    437     } else {
    438 
    439 	/* Unwrap Shape functions */
    440 	DMX_UNWRAP(SetShape, dmxScreen, pScreen);
    441 
    442 	/* Unwrap the pScreen functions */
    443 	DMX_UNWRAP(CreateGC, dmxScreen, pScreen);
    444 
    445 	DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
    446 	DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen);
    447 	DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
    448 	DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
    449 	DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
    450 	DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
    451 	DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
    452 	DMX_UNWRAP(WindowExposures, dmxScreen, pScreen);
    453 	DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
    454 
    455 	DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
    456 	DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
    457 
    458 	DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
    459 
    460 	DMX_UNWRAP(GetImage, dmxScreen, pScreen);
    461 	DMX_UNWRAP(GetSpans, dmxScreen, pScreen);
    462 
    463 	DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen);
    464 	DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen);
    465 	DMX_UNWRAP(BitmapToRegion, dmxScreen, pScreen);
    466 
    467 	DMX_UNWRAP(RealizeFont, dmxScreen, pScreen);
    468 	DMX_UNWRAP(UnrealizeFont, dmxScreen, pScreen);
    469 
    470 	DMX_UNWRAP(CreateColormap, dmxScreen, pScreen);
    471 	DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen);
    472 	DMX_UNWRAP(InstallColormap, dmxScreen, pScreen);
    473 	DMX_UNWRAP(StoreColors, dmxScreen, pScreen);
    474     }
    475 
    476     DMX_UNWRAP(SaveScreen, dmxScreen, pScreen);
    477 
    478     if (dmxScreen->beDisplay) {
    479 	dmxBECloseScreen(pScreen);
    480 
    481 #if 1
    482 	/* Free visuals, depths and pixmap formats here so that they
    483 	 * won't be freed when a screen is detached, thereby allowing
    484 	 * the screen to be reattached to be compared to the one
    485 	 * previously removed.
    486 	 */
    487 	XFree(dmxScreen->beVisuals);
    488 	dmxScreen->beVisuals = NULL;
    489 
    490 	XFree(dmxScreen->beDepths);
    491 	dmxScreen->beDepths = NULL;
    492 
    493 	XFree(dmxScreen->bePixmapFormats);
    494 	dmxScreen->bePixmapFormats = NULL;
    495 #endif
    496     }
    497 
    498     DMX_UNWRAP(CloseScreen, dmxScreen, pScreen);
    499     return pScreen->CloseScreen(idx, pScreen);
    500 }
    501 
    502 static Bool dmxSaveScreen(ScreenPtr pScreen, int what)
    503 {
    504     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
    505 
    506     if (dmxScreen->beDisplay) {
    507 	switch (what) {
    508 	case SCREEN_SAVER_OFF:
    509 	case SCREEN_SAVER_FORCER:
    510 	    XResetScreenSaver(dmxScreen->beDisplay);
    511 	    dmxSync(dmxScreen, FALSE);
    512 	    break;
    513 	case SCREEN_SAVER_ON:
    514 	case SCREEN_SAVER_CYCLE:
    515 	    XActivateScreenSaver(dmxScreen->beDisplay);
    516 	    dmxSync(dmxScreen, FALSE);
    517 	    break;
    518 	}
    519     }
    520 
    521     return TRUE;
    522 }
    523