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