1 /*
2 
3 Copyright 1993 by Davor Matic
4 
5 Permission to use, copy, modify, distribute, and sell this software
6 and its documentation for any purpose is hereby granted without fee,
7 provided that the above copyright notice appear in all copies and that
8 both that copyright notice and this permission notice appear in
9 supporting documentation.  Davor Matic makes no representations about
10 the suitability of this software for any purpose.  It is provided "as
11 is" 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 
45 Window xnestDefaultWindows[MAXSCREENS];
46 Window xnestScreenSaverWindows[MAXSCREENS];
47 DevPrivateKeyRec xnestCursorScreenKeyRec;
48 
49 ScreenPtr
xnestScreen(Window window)50 xnestScreen(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 
61 static int
offset(unsigned long mask)62 offset(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 
72 static Bool
xnestSaveScreen(ScreenPtr pScreen,int what)73 xnestSaveScreen(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 
104 static Bool
xnestCursorOffScreen(ScreenPtr * ppScreen,int * x,int * y)105 xnestCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
106 {
107     return FALSE;
108 }
109 
110 static void
xnestCrossScreen(ScreenPtr pScreen,Bool entering)111 xnestCrossScreen(ScreenPtr pScreen, Bool entering)
112 {
113 }
114 
115 static miPointerScreenFuncRec xnestPointerCursorFuncs = {
116     xnestCursorOffScreen,
117     xnestCrossScreen,
118     miPointerWarpCursor
119 };
120 
121 static miPointerSpriteFuncRec xnestPointerSpriteFuncs = {
122     xnestRealizeCursor,
123     xnestUnrealizeCursor,
124     xnestSetCursor,
125     xnestMoveCursor,
126     xnestDeviceCursorInitialize,
127     xnestDeviceCursorCleanup
128 };
129 
130 Bool
xnestOpenScreen(ScreenPtr pScreen,int argc,char * argv[])131 xnestOpenScreen(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 
408 Bool
xnestCloseScreen(ScreenPtr pScreen)409 xnestCloseScreen(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