Screen.c revision 05b261ec
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
45Window xnestDefaultWindows[MAXSCREENS];
46Window xnestScreenSaverWindows[MAXSCREENS];
47
48#ifdef GLXEXT
49extern void GlxWrapInitVisuals(miInitVisualsProcPtr *);
50#endif
51
52static int xnestScreenGeneration = -1;
53
54ScreenPtr
55xnestScreen(Window window)
56{
57  int i;
58
59  for (i = 0; i < xnestNumScreens; i++)
60    if (xnestDefaultWindows[i] == window)
61      return screenInfo.screens[i];
62
63  return NULL;
64}
65
66static int
67offset(unsigned long mask)
68{
69  int count;
70
71  for (count = 0; !(mask & 1) && count < 32; count++)
72    mask >>= 1;
73
74  return count;
75}
76
77static Bool
78xnestSaveScreen(ScreenPtr pScreen, int what)
79{
80  if (xnestSoftwareScreenSaver)
81    return False;
82  else {
83    switch (what) {
84    case SCREEN_SAVER_ON:
85      XMapRaised(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]);
86      xnestSetScreenSaverColormapWindow(pScreen);
87      break;
88
89    case SCREEN_SAVER_OFF:
90      XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]);
91      xnestSetInstalledColormapWindows(pScreen);
92      break;
93
94    case SCREEN_SAVER_FORCER:
95      lastEventTime = GetTimeInMillis();
96      XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]);
97      xnestSetInstalledColormapWindows(pScreen);
98      break;
99
100    case SCREEN_SAVER_CYCLE:
101      XUnmapWindow(xnestDisplay, xnestScreenSaverWindows[pScreen->myNum]);
102      xnestSetInstalledColormapWindows(pScreen);
103      break;
104    }
105    return True;
106  }
107}
108
109static Bool
110xnestCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
111{
112    return FALSE;
113}
114
115static void
116xnestCrossScreen(ScreenPtr pScreen, Bool entering)
117{
118}
119
120static miPointerScreenFuncRec xnestPointerCursorFuncs =
121{
122    xnestCursorOffScreen,
123    xnestCrossScreen,
124    miPointerWarpCursor
125};
126
127static miPointerSpriteFuncRec xnestPointerSpriteFuncs =
128{
129    xnestRealizeCursor,
130    xnestUnrealizeCursor,
131    xnestSetCursor,
132    xnestMoveCursor,
133};
134
135Bool
136xnestOpenScreen(int index, ScreenPtr pScreen, int argc, char *argv[])
137{
138  VisualPtr visuals;
139  DepthPtr depths;
140  int numVisuals, numDepths;
141  int i, j, depthIndex;
142  unsigned long valuemask;
143  XSetWindowAttributes attributes;
144  XWindowAttributes gattributes;
145  XSizeHints sizeHints;
146  VisualID defaultVisual;
147  int rootDepth;
148
149  if (!(AllocateWindowPrivate(pScreen, xnestWindowPrivateIndex,
150			    sizeof(xnestPrivWin))  &&
151	  AllocateGCPrivate(pScreen, xnestGCPrivateIndex,
152			    sizeof(xnestPrivGC))))
153    return False;
154
155  if (xnestScreenGeneration != serverGeneration) {
156      if ((xnestPixmapPrivateIndex = AllocatePixmapPrivateIndex()) < 0)
157	  return False;
158      xnestScreenGeneration = serverGeneration;
159  }
160
161  if (!AllocatePixmapPrivate(pScreen,xnestPixmapPrivateIndex,
162			     sizeof (xnestPrivPixmap)))
163      return False;
164  visuals = (VisualPtr)xalloc(xnestNumVisuals * sizeof(VisualRec));
165  numVisuals = 0;
166
167  depths = (DepthPtr)xalloc(MAXDEPTH * sizeof(DepthRec));
168  depths[0].depth = 1;
169  depths[0].numVids = 0;
170  depths[0].vids = (VisualID *)xalloc(MAXVISUALSPERDEPTH * sizeof(VisualID));
171  numDepths = 1;
172
173  for (i = 0; i < xnestNumVisuals; i++) {
174    visuals[numVisuals].class = xnestVisuals[i].class;
175    visuals[numVisuals].bitsPerRGBValue = xnestVisuals[i].bits_per_rgb;
176    visuals[numVisuals].ColormapEntries = xnestVisuals[i].colormap_size;
177    visuals[numVisuals].nplanes = xnestVisuals[i].depth;
178    visuals[numVisuals].redMask = xnestVisuals[i].red_mask;
179    visuals[numVisuals].greenMask = xnestVisuals[i].green_mask;
180    visuals[numVisuals].blueMask = xnestVisuals[i].blue_mask;
181    visuals[numVisuals].offsetRed = offset(xnestVisuals[i].red_mask);
182    visuals[numVisuals].offsetGreen = offset(xnestVisuals[i].green_mask);
183    visuals[numVisuals].offsetBlue = offset(xnestVisuals[i].blue_mask);
184
185    /* Check for and remove duplicates. */
186    for (j = 0; j < numVisuals; j++) {
187      if (visuals[numVisuals].class           == visuals[j].class           &&
188	  visuals[numVisuals].bitsPerRGBValue == visuals[j].bitsPerRGBValue &&
189	  visuals[numVisuals].ColormapEntries == visuals[j].ColormapEntries &&
190	  visuals[numVisuals].nplanes         == visuals[j].nplanes         &&
191	  visuals[numVisuals].redMask         == visuals[j].redMask         &&
192	  visuals[numVisuals].greenMask       == visuals[j].greenMask       &&
193	  visuals[numVisuals].blueMask        == visuals[j].blueMask        &&
194	  visuals[numVisuals].offsetRed       == visuals[j].offsetRed       &&
195	  visuals[numVisuals].offsetGreen     == visuals[j].offsetGreen     &&
196	  visuals[numVisuals].offsetBlue      == visuals[j].offsetBlue)
197	break;
198    }
199    if (j < numVisuals)
200      break;
201
202    visuals[numVisuals].vid = FakeClientID(0);
203
204    depthIndex = UNDEFINED;
205    for (j = 0; j < numDepths; j++)
206      if (depths[j].depth == xnestVisuals[i].depth) {
207	depthIndex = j;
208	break;
209      }
210
211    if (depthIndex == UNDEFINED) {
212      depthIndex = numDepths;
213      depths[depthIndex].depth = xnestVisuals[i].depth;
214      depths[depthIndex].numVids = 0;
215      depths[depthIndex].vids =
216	(VisualID *)xalloc(MAXVISUALSPERDEPTH * sizeof(VisualID));
217      numDepths++;
218    }
219    if (depths[depthIndex].numVids >= MAXVISUALSPERDEPTH) {
220	FatalError("Visual table overflow");
221    }
222    depths[depthIndex].vids[depths[depthIndex].numVids] =
223      visuals[numVisuals].vid;
224    depths[depthIndex].numVids++;
225
226    numVisuals++;
227  }
228  visuals = (VisualPtr)xrealloc(visuals, numVisuals * sizeof(VisualRec));
229
230  defaultVisual = visuals[xnestDefaultVisualIndex].vid;
231  rootDepth = visuals[xnestDefaultVisualIndex].nplanes;
232
233#ifdef GLXEXT
234  {
235    miInitVisualsProcPtr proc = NULL;
236
237    GlxWrapInitVisuals(&proc);
238    /* GlxInitVisuals ignores the last three arguments. */
239    proc(&visuals, &depths, &numVisuals, &numDepths,
240	 &rootDepth, &defaultVisual, 0, 0, 0);
241  }
242#endif
243
244  if (xnestParentWindow != 0) {
245    XGetWindowAttributes(xnestDisplay, xnestParentWindow, &gattributes);
246    xnestWidth = gattributes.width;
247    xnestHeight = gattributes.height;
248  }
249
250  /* myNum */
251  /* id */
252  miScreenInit(pScreen, NULL, xnestWidth, xnestHeight, 1, 1, xnestWidth,
253	       rootDepth,
254	       numDepths, depths,
255	       defaultVisual, /* root visual */
256	       numVisuals, visuals);
257
258/*  miInitializeBackingStore(pScreen); */
259
260  pScreen->defColormap = (Colormap) FakeClientID(0);
261  pScreen->minInstalledCmaps = MINCMAPS;
262  pScreen->maxInstalledCmaps = MAXCMAPS;
263  pScreen->backingStoreSupport = NotUseful;
264  pScreen->saveUnderSupport = NotUseful;
265  pScreen->whitePixel = xnestWhitePixel;
266  pScreen->blackPixel = xnestBlackPixel;
267  /* rgf */
268  /* GCperDepth */
269  /* PixmapPerDepth */
270  pScreen->devPrivate = NULL;
271  /* WindowPrivateLen */
272  /* WindowPrivateSizes */
273  /* totalWindowSize */
274  /* GCPrivateLen */
275  /* GCPrivateSizes */
276  /* totalGCSize */
277
278  /* Random screen procedures */
279
280  pScreen->QueryBestSize = xnestQueryBestSize;
281  pScreen->SaveScreen = xnestSaveScreen;
282  pScreen->GetImage = xnestGetImage;
283  pScreen->GetSpans = xnestGetSpans;
284  pScreen->PointerNonInterestBox = NULL;
285  pScreen->SourceValidate = NULL;
286
287  /* Window Procedures */
288
289  pScreen->CreateWindow = xnestCreateWindow;
290  pScreen->DestroyWindow = xnestDestroyWindow;
291  pScreen->PositionWindow = xnestPositionWindow;
292  pScreen->ChangeWindowAttributes = xnestChangeWindowAttributes;
293  pScreen->RealizeWindow = xnestRealizeWindow;
294  pScreen->UnrealizeWindow = xnestUnrealizeWindow;
295  pScreen->PostValidateTree = NULL;
296  pScreen->WindowExposures = xnestWindowExposures;
297  pScreen->PaintWindowBackground = xnestPaintWindowBackground;
298  pScreen->PaintWindowBorder = xnestPaintWindowBorder;
299  pScreen->CopyWindow = xnestCopyWindow;
300  pScreen->ClipNotify = xnestClipNotify;
301
302  /* Pixmap procedures */
303
304  pScreen->CreatePixmap = xnestCreatePixmap;
305  pScreen->DestroyPixmap = xnestDestroyPixmap;
306
307  /* Backing store procedures */
308
309  pScreen->SaveDoomedAreas = NULL;
310  pScreen->RestoreAreas = NULL;
311  pScreen->ExposeCopy = NULL;
312  pScreen->TranslateBackingStore = NULL;
313  pScreen->ClearBackingStore = NULL;
314  pScreen->DrawGuarantee = NULL;
315
316  /* Font procedures */
317
318  pScreen->RealizeFont = xnestRealizeFont;
319  pScreen->UnrealizeFont = xnestUnrealizeFont;
320
321  /* GC procedures */
322
323  pScreen->CreateGC = xnestCreateGC;
324
325  /* Colormap procedures */
326
327  pScreen->CreateColormap = xnestCreateColormap;
328  pScreen->DestroyColormap = xnestDestroyColormap;
329  pScreen->InstallColormap = xnestInstallColormap;
330  pScreen->UninstallColormap = xnestUninstallColormap;
331  pScreen->ListInstalledColormaps = xnestListInstalledColormaps;
332  pScreen->StoreColors = xnestStoreColors;
333  pScreen->ResolveColor = xnestResolveColor;
334
335   pScreen->BitmapToRegion = xnestPixmapToRegion;
336
337  /* OS layer procedures */
338
339  pScreen->BlockHandler = (ScreenBlockHandlerProcPtr)NoopDDA;
340  pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr)NoopDDA;
341  pScreen->blockData = NULL;
342  pScreen->wakeupData = NULL;
343
344  miPointerInitialize (pScreen, &xnestPointerSpriteFuncs,
345		       &xnestPointerCursorFuncs, True);
346
347  pScreen->mmWidth = xnestWidth * DisplayWidthMM(xnestDisplay,
348		       DefaultScreen(xnestDisplay)) /
349			 DisplayWidth(xnestDisplay,
350			   DefaultScreen(xnestDisplay));
351  pScreen->mmHeight = xnestHeight * DisplayHeightMM(xnestDisplay,
352		        DefaultScreen(xnestDisplay)) /
353			  DisplayHeight(xnestDisplay,
354			    DefaultScreen(xnestDisplay));
355
356  /* overwrite miCloseScreen with our own */
357  pScreen->CloseScreen = xnestCloseScreen;
358
359  if (!miScreenDevPrivateInit(pScreen, xnestWidth, NULL))
360      return FALSE;
361
362#ifdef SHAPE
363  /* overwrite miSetShape with our own */
364  pScreen->SetShape = xnestSetShape;
365#endif /* SHAPE */
366
367  /* devPrivates */
368
369#define POSITION_OFFSET (pScreen->myNum * (xnestWidth + xnestHeight) / 32)
370
371  if (xnestDoFullGeneration) {
372
373    valuemask = CWBackPixel | CWEventMask | CWColormap;
374    attributes.background_pixel = xnestWhitePixel;
375    attributes.event_mask = xnestEventMask;
376    attributes.colormap = xnestDefaultVisualColormap(xnestDefaultVisual(pScreen));
377
378    if (xnestParentWindow != 0) {
379      xnestDefaultWindows[pScreen->myNum] = xnestParentWindow;
380      XSelectInput (xnestDisplay, xnestDefaultWindows[pScreen->myNum],
381		    xnestEventMask);
382    } else
383      xnestDefaultWindows[pScreen->myNum] =
384	XCreateWindow(xnestDisplay,
385		      DefaultRootWindow(xnestDisplay),
386		      xnestX + POSITION_OFFSET,
387		      xnestY + POSITION_OFFSET,
388		      xnestWidth, xnestHeight,
389		      xnestBorderWidth,
390		      pScreen->rootDepth,
391		      InputOutput,
392		      xnestDefaultVisual(pScreen),
393		      valuemask, &attributes);
394
395    if (!xnestWindowName)
396      xnestWindowName = argv[0];
397
398    sizeHints.flags = PPosition | PSize | PMaxSize;
399    sizeHints.x = xnestX + POSITION_OFFSET;
400    sizeHints.y = xnestY + POSITION_OFFSET;
401    sizeHints.width = sizeHints.max_width = xnestWidth;
402    sizeHints.height = sizeHints.max_height = xnestHeight;
403    if (xnestUserGeometry & XValue || xnestUserGeometry & YValue)
404      sizeHints.flags |= USPosition;
405    if (xnestUserGeometry & WidthValue || xnestUserGeometry & HeightValue)
406      sizeHints.flags |= USSize;
407    XSetStandardProperties(xnestDisplay,
408			   xnestDefaultWindows[pScreen->myNum],
409			   xnestWindowName,
410			   xnestWindowName,
411			   xnestIconBitmap,
412			   argv, argc, &sizeHints);
413
414    XMapWindow(xnestDisplay, xnestDefaultWindows[pScreen->myNum]);
415
416    valuemask = CWBackPixmap | CWColormap;
417    attributes.background_pixmap = xnestScreenSaverPixmap;
418    attributes.colormap =
419      DefaultColormap(xnestDisplay, DefaultScreen(xnestDisplay));
420    xnestScreenSaverWindows[pScreen->myNum] =
421      XCreateWindow(xnestDisplay,
422		    xnestDefaultWindows[pScreen->myNum],
423		    0, 0, xnestWidth, xnestHeight, 0,
424		    DefaultDepth(xnestDisplay, DefaultScreen(xnestDisplay)),
425		    InputOutput,
426		    DefaultVisual(xnestDisplay, DefaultScreen(xnestDisplay)),
427		    valuemask, &attributes);
428  }
429
430  if (!xnestCreateDefaultColormap(pScreen)) return False;
431
432  return True;
433}
434
435Bool
436xnestCloseScreen(int index, ScreenPtr pScreen)
437{
438  int i;
439
440  for (i = 0; i < pScreen->numDepths; i++)
441    xfree(pScreen->allowedDepths[i].vids);
442  xfree(pScreen->allowedDepths);
443  xfree(pScreen->visuals);
444  xfree(pScreen->devPrivate);
445
446  /*
447    If xnestDoFullGeneration all x resources will be destroyed upon closing
448    the display connection.  There is no need to generate extra protocol.
449    */
450
451  return True;
452}
453