1/* 2 3Copyright 1993 by Davor Matic 4 5Permission to use, copy, modify, distribute, and sell this software 6and its documentation for any purpose is hereby granted without fee, 7provided that the above copyright notice appear in all copies and that 8both that copyright notice and this permission notice appear in 9supporting documentation. Davor Matic makes no representations about 10the suitability of this software for any purpose. It is provided "as 11is" without express or implied warranty. 12 13*/ 14 15#ifdef HAVE_XNEST_CONFIG_H 16#include <xnest-config.h> 17#endif 18 19#include <X11/X.h> 20#include <X11/Xproto.h> 21#include "scrnintstr.h" 22#include "dix.h" 23#include "mi.h" 24#include "micmap.h" 25#include "colormapst.h" 26#include "resource.h" 27 28#include "Xnest.h" 29 30#include "Display.h" 31#include "Screen.h" 32#include "XNGC.h" 33#include "GCOps.h" 34#include "Drawable.h" 35#include "XNFont.h" 36#include "Color.h" 37#include "XNCursor.h" 38#include "Visual.h" 39#include "Events.h" 40#include "Init.h" 41#include "mipointer.h" 42#include "Args.h" 43#include "mipointrst.h" 44 45Window xnestDefaultWindows[MAXSCREENS]; 46Window xnestScreenSaverWindows[MAXSCREENS]; 47DevPrivateKeyRec xnestCursorScreenKeyRec; 48 49ScreenPtr 50xnestScreen(Window window) 51{ 52 int i; 53 54 for (i = 0; i < xnestNumScreens; i++) 55 if (xnestDefaultWindows[i] == window) 56 return screenInfo.screens[i]; 57 58 return NULL; 59} 60 61static int 62offset(unsigned long mask) 63{ 64 int count; 65 66 for (count = 0; !(mask & 1) && count < 32; count++) 67 mask >>= 1; 68 69 return count; 70} 71 72static Bool 73xnestSaveScreen(ScreenPtr pScreen, int what) 74{ 75 if (xnestSoftwareScreenSaver) 76 return False; 77 else { 78 switch (what) { 79 case SCREEN_SAVER_ON: 80 XMapRaised(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); 81 xnestSetScreenSaverColormapWindow(pScreen); 82 break; 83 84 case SCREEN_SAVER_OFF: 85 XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); 86 xnestSetInstalledColormapWindows(pScreen); 87 break; 88 89 case SCREEN_SAVER_FORCER: 90 lastEventTime = GetTimeInMillis(); 91 XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); 92 xnestSetInstalledColormapWindows(pScreen); 93 break; 94 95 case SCREEN_SAVER_CYCLE: 96 XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]); 97 xnestSetInstalledColormapWindows(pScreen); 98 break; 99 } 100 return True; 101 } 102} 103 104static Bool 105xnestCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) 106{ 107 return FALSE; 108} 109 110static void 111xnestCrossScreen(ScreenPtr pScreen, Bool entering) 112{ 113} 114 115static miPointerScreenFuncRec xnestPointerCursorFuncs = { 116 xnestCursorOffScreen, 117 xnestCrossScreen, 118 miPointerWarpCursor 119}; 120 121static miPointerSpriteFuncRec xnestPointerSpriteFuncs = { 122 xnestRealizeCursor, 123 xnestUnrealizeCursor, 124 xnestSetCursor, 125 xnestMoveCursor, 126 xnestDeviceCursorInitialize, 127 xnestDeviceCursorCleanup 128}; 129 130Bool 131xnestOpenScreen(ScreenPtr pScreen, int argc, char *argv[]) 132{ 133 VisualPtr visuals; 134 DepthPtr depths; 135 int numVisuals, numDepths; 136 int i, j, depthIndex; 137 unsigned long valuemask; 138 XSetWindowAttributes attributes; 139 XWindowAttributes gattributes; 140 XSizeHints sizeHints; 141 VisualID defaultVisual; 142 int rootDepth; 143 miPointerScreenPtr PointPriv; 144 145 if (!dixRegisterPrivateKey 146 (&xnestWindowPrivateKeyRec, PRIVATE_WINDOW, sizeof(xnestPrivWin))) 147 return FALSE; 148 if (!dixRegisterPrivateKey 149 (&xnestGCPrivateKeyRec, PRIVATE_GC, sizeof(xnestPrivGC))) 150 return FALSE; 151 if (!dixRegisterPrivateKey 152 (&xnestPixmapPrivateKeyRec, PRIVATE_PIXMAP, sizeof(xnestPrivPixmap))) 153 return FALSE; 154 if (!dixRegisterPrivateKey 155 (&xnestColormapPrivateKeyRec, PRIVATE_COLORMAP, 156 sizeof(xnestPrivColormap))) 157 return FALSE; 158 if (!dixRegisterPrivateKey(&xnestCursorScreenKeyRec, PRIVATE_SCREEN, 0)) 159 return FALSE; 160 161 visuals = xallocarray(xnestNumVisuals, sizeof(VisualRec)); 162 numVisuals = 0; 163 164 depths = (DepthPtr) malloc(MAXDEPTH * sizeof(DepthRec)); 165 depths[0].depth = 1; 166 depths[0].numVids = 0; 167 depths[0].vids = (VisualID *) malloc(MAXVISUALSPERDEPTH * sizeof(VisualID)); 168 numDepths = 1; 169 170 for (i = 0; i < xnestNumVisuals; i++) { 171 visuals[numVisuals].class = xnestVisuals[i].class; 172 visuals[numVisuals].bitsPerRGBValue = xnestVisuals[i].bits_per_rgb; 173 visuals[numVisuals].ColormapEntries = xnestVisuals[i].colormap_size; 174 visuals[numVisuals].nplanes = xnestVisuals[i].depth; 175 visuals[numVisuals].redMask = xnestVisuals[i].red_mask; 176 visuals[numVisuals].greenMask = xnestVisuals[i].green_mask; 177 visuals[numVisuals].blueMask = xnestVisuals[i].blue_mask; 178 visuals[numVisuals].offsetRed = offset(xnestVisuals[i].red_mask); 179 visuals[numVisuals].offsetGreen = offset(xnestVisuals[i].green_mask); 180 visuals[numVisuals].offsetBlue = offset(xnestVisuals[i].blue_mask); 181 182 /* Check for and remove duplicates. */ 183 for (j = 0; j < numVisuals; j++) { 184 if (visuals[numVisuals].class == visuals[j].class && 185 visuals[numVisuals].bitsPerRGBValue == 186 visuals[j].bitsPerRGBValue && 187 visuals[numVisuals].ColormapEntries == 188 visuals[j].ColormapEntries && 189 visuals[numVisuals].nplanes == visuals[j].nplanes && 190 visuals[numVisuals].redMask == visuals[j].redMask && 191 visuals[numVisuals].greenMask == visuals[j].greenMask && 192 visuals[numVisuals].blueMask == visuals[j].blueMask && 193 visuals[numVisuals].offsetRed == visuals[j].offsetRed && 194 visuals[numVisuals].offsetGreen == visuals[j].offsetGreen && 195 visuals[numVisuals].offsetBlue == visuals[j].offsetBlue) 196 break; 197 } 198 if (j < numVisuals) 199 break; 200 201 visuals[numVisuals].vid = FakeClientID(0); 202 203 depthIndex = UNDEFINED; 204 for (j = 0; j < numDepths; j++) 205 if (depths[j].depth == xnestVisuals[i].depth) { 206 depthIndex = j; 207 break; 208 } 209 210 if (depthIndex == UNDEFINED) { 211 depthIndex = numDepths; 212 depths[depthIndex].depth = xnestVisuals[i].depth; 213 depths[depthIndex].numVids = 0; 214 depths[depthIndex].vids = 215 (VisualID *) malloc(MAXVISUALSPERDEPTH * sizeof(VisualID)); 216 numDepths++; 217 } 218 if (depths[depthIndex].numVids >= MAXVISUALSPERDEPTH) { 219 FatalError("Visual table overflow"); 220 } 221 depths[depthIndex].vids[depths[depthIndex].numVids] = 222 visuals[numVisuals].vid; 223 depths[depthIndex].numVids++; 224 225 numVisuals++; 226 } 227 visuals = reallocarray(visuals, numVisuals, sizeof(VisualRec)); 228 229 defaultVisual = visuals[xnestDefaultVisualIndex].vid; 230 rootDepth = visuals[xnestDefaultVisualIndex].nplanes; 231 232 if (xnestParentWindow != 0) { 233 XGetWindowAttributes(xnestDisplay, xnestParentWindow, &gattributes); 234 xnestWidth = gattributes.width; 235 xnestHeight = gattributes.height; 236 } 237 238 /* myNum */ 239 /* id */ 240 miScreenInit(pScreen, NULL, xnestWidth, xnestHeight, 1, 1, xnestWidth, rootDepth, numDepths, depths, defaultVisual, /* root visual */ 241 numVisuals, visuals); 242 243 pScreen->defColormap = (Colormap) FakeClientID(0); 244 pScreen->minInstalledCmaps = MINCMAPS; 245 pScreen->maxInstalledCmaps = MAXCMAPS; 246 pScreen->backingStoreSupport = NotUseful; 247 pScreen->saveUnderSupport = NotUseful; 248 pScreen->whitePixel = xnestWhitePixel; 249 pScreen->blackPixel = xnestBlackPixel; 250 /* GCperDepth */ 251 /* defaultStipple */ 252 pScreen->devPrivate = NULL; 253 /* WindowPrivateLen */ 254 /* WindowPrivateSizes */ 255 /* totalWindowSize */ 256 /* GCPrivateLen */ 257 /* GCPrivateSizes */ 258 /* totalGCSize */ 259 260 /* Random screen procedures */ 261 262 pScreen->QueryBestSize = xnestQueryBestSize; 263 pScreen->SaveScreen = xnestSaveScreen; 264 pScreen->GetImage = xnestGetImage; 265 pScreen->GetSpans = xnestGetSpans; 266 267 /* Window Procedures */ 268 269 pScreen->CreateWindow = xnestCreateWindow; 270 pScreen->DestroyWindow = xnestDestroyWindow; 271 pScreen->PositionWindow = xnestPositionWindow; 272 pScreen->ChangeWindowAttributes = xnestChangeWindowAttributes; 273 pScreen->RealizeWindow = xnestRealizeWindow; 274 pScreen->UnrealizeWindow = xnestUnrealizeWindow; 275 pScreen->PostValidateTree = NULL; 276 pScreen->WindowExposures = xnestWindowExposures; 277 pScreen->CopyWindow = xnestCopyWindow; 278 pScreen->ClipNotify = xnestClipNotify; 279 280 /* Pixmap procedures */ 281 282 pScreen->CreatePixmap = xnestCreatePixmap; 283 pScreen->DestroyPixmap = xnestDestroyPixmap; 284 pScreen->ModifyPixmapHeader = xnestModifyPixmapHeader; 285 286 /* Font procedures */ 287 288 pScreen->RealizeFont = xnestRealizeFont; 289 pScreen->UnrealizeFont = xnestUnrealizeFont; 290 291 /* GC procedures */ 292 293 pScreen->CreateGC = xnestCreateGC; 294 295 /* Colormap procedures */ 296 297 pScreen->CreateColormap = xnestCreateColormap; 298 pScreen->DestroyColormap = xnestDestroyColormap; 299 pScreen->InstallColormap = xnestInstallColormap; 300 pScreen->UninstallColormap = xnestUninstallColormap; 301 pScreen->ListInstalledColormaps = xnestListInstalledColormaps; 302 pScreen->StoreColors = xnestStoreColors; 303 pScreen->ResolveColor = xnestResolveColor; 304 305 pScreen->BitmapToRegion = xnestPixmapToRegion; 306 307 /* OS layer procedures */ 308 309 pScreen->BlockHandler = (ScreenBlockHandlerProcPtr) NoopDDA; 310 pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr) NoopDDA; 311 312 miDCInitialize(pScreen, &xnestPointerCursorFuncs); /* init SW rendering */ 313 PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 314 xnestCursorFuncs.spriteFuncs = PointPriv->spriteFuncs; 315 dixSetPrivate(&pScreen->devPrivates, xnestCursorScreenKey, 316 &xnestCursorFuncs); 317 PointPriv->spriteFuncs = &xnestPointerSpriteFuncs; 318 319 pScreen->mmWidth = xnestWidth * DisplayWidthMM(xnestDisplay, 320 DefaultScreen(xnestDisplay)) 321 / DisplayWidth(xnestDisplay, DefaultScreen(xnestDisplay)); 322 pScreen->mmHeight = 323 xnestHeight * DisplayHeightMM(xnestDisplay, 324 DefaultScreen(xnestDisplay)) / 325 DisplayHeight(xnestDisplay, DefaultScreen(xnestDisplay)); 326 327 /* overwrite miCloseScreen with our own */ 328 pScreen->CloseScreen = xnestCloseScreen; 329 330 if (!miScreenDevPrivateInit(pScreen, xnestWidth, NULL)) 331 return FALSE; 332 333 /* overwrite miSetShape with our own */ 334 pScreen->SetShape = xnestSetShape; 335 336 /* devPrivates */ 337 338#define POSITION_OFFSET (pScreen->myNum * (xnestWidth + xnestHeight) / 32) 339 340 if (xnestDoFullGeneration) { 341 342 valuemask = CWBackPixel | CWEventMask | CWColormap; 343 attributes.background_pixel = xnestWhitePixel; 344 attributes.event_mask = xnestEventMask; 345 attributes.colormap = 346 xnestDefaultVisualColormap(xnestDefaultVisual(pScreen)); 347 348 if (xnestParentWindow != 0) { 349 xnestDefaultWindows[pScreen->myNum] = xnestParentWindow; 350 XSelectInput(xnestDisplay, xnestDefaultWindows[pScreen->myNum], 351 xnestEventMask); 352 } 353 else 354 xnestDefaultWindows[pScreen->myNum] = 355 XCreateWindow(xnestDisplay, 356 DefaultRootWindow(xnestDisplay), 357 xnestX + POSITION_OFFSET, 358 xnestY + POSITION_OFFSET, 359 xnestWidth, xnestHeight, 360 xnestBorderWidth, 361 pScreen->rootDepth, 362 InputOutput, 363 xnestDefaultVisual(pScreen), 364 valuemask, &attributes); 365 366 if (!xnestWindowName) 367 xnestWindowName = argv[0]; 368 369 sizeHints.flags = PPosition | PSize | PMaxSize; 370 sizeHints.x = xnestX + POSITION_OFFSET; 371 sizeHints.y = xnestY + POSITION_OFFSET; 372 sizeHints.width = sizeHints.max_width = xnestWidth; 373 sizeHints.height = sizeHints.max_height = xnestHeight; 374 if (xnestUserGeometry & XValue || xnestUserGeometry & YValue) 375 sizeHints.flags |= USPosition; 376 if (xnestUserGeometry & WidthValue || xnestUserGeometry & HeightValue) 377 sizeHints.flags |= USSize; 378 XSetStandardProperties(xnestDisplay, 379 xnestDefaultWindows[pScreen->myNum], 380 xnestWindowName, 381 xnestWindowName, 382 xnestIconBitmap, argv, argc, &sizeHints); 383 384 XMapWindow(xnestDisplay, xnestDefaultWindows[pScreen->myNum]); 385 386 valuemask = CWBackPixmap | CWColormap; 387 attributes.background_pixmap = xnestScreenSaverPixmap; 388 attributes.colormap = 389 DefaultColormap(xnestDisplay, DefaultScreen(xnestDisplay)); 390 xnestScreenSaverWindows[pScreen->myNum] = 391 XCreateWindow(xnestDisplay, 392 xnestDefaultWindows[pScreen->myNum], 393 0, 0, xnestWidth, xnestHeight, 0, 394 DefaultDepth(xnestDisplay, 395 DefaultScreen(xnestDisplay)), 396 InputOutput, DefaultVisual(xnestDisplay, 397 DefaultScreen 398 (xnestDisplay)), valuemask, 399 &attributes); 400 } 401 402 if (!xnestCreateDefaultColormap(pScreen)) 403 return False; 404 405 return True; 406} 407 408Bool 409xnestCloseScreen(ScreenPtr pScreen) 410{ 411 int i; 412 413 for (i = 0; i < pScreen->numDepths; i++) 414 free(pScreen->allowedDepths[i].vids); 415 free(pScreen->allowedDepths); 416 free(pScreen->visuals); 417 free(pScreen->devPrivate); 418 419 /* 420 If xnestDoFullGeneration all x resources will be destroyed upon closing 421 the display connection. There is no need to generate extra protocol. 422 */ 423 424 return True; 425} 426