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