1 /*
2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28 /*
29 * Authors:
30 * Kevin E. Martin <kem@redhat.com>
31 * David H. Dawes <dawes@xfree86.org>
32 *
33 */
34
35 /** \file
36 * This file provides support for screen initialization. */
37
38 #ifdef HAVE_DMX_CONFIG_H
39 #include <dmx-config.h>
40 #endif
41
42 #include "dmx.h"
43 #include "dmxsync.h"
44 #include "dmxscrinit.h"
45 #include "dmxcursor.h"
46 #include "dmxgc.h"
47 #include "dmxgcops.h"
48 #include "dmxwindow.h"
49 #include "dmxpixmap.h"
50 #include "dmxfont.h"
51 #include "dmxcmap.h"
52 #include "dmxprop.h"
53 #include "dmxdpms.h"
54
55 #include "dmxpict.h"
56
57 #include "fb.h"
58 #include "mipointer.h"
59 #include "micmap.h"
60
61 #include <X11/fonts/libxfont2.h>
62
63 extern Bool dmxCloseScreen(ScreenPtr pScreen);
64 static Bool dmxSaveScreen(ScreenPtr pScreen, int what);
65
66 static unsigned long dmxGeneration;
67 static unsigned long *dmxCursorGeneration;
68
69 DevPrivateKeyRec dmxGCPrivateKeyRec;
70 DevPrivateKeyRec dmxWinPrivateKeyRec;
71 DevPrivateKeyRec dmxPixPrivateKeyRec;
72 int dmxFontPrivateIndex; /**< Private index for Fonts */
73 DevPrivateKeyRec dmxScreenPrivateKeyRec;
74 DevPrivateKeyRec dmxColormapPrivateKeyRec;
75 DevPrivateKeyRec dmxPictPrivateKeyRec;
76 DevPrivateKeyRec dmxGlyphSetPrivateKeyRec;
77
78 #ifdef DPMSExtension
79 static void
dmxDPMS(ScreenPtr pScreen,int level)80 dmxDPMS(ScreenPtr pScreen, int level)
81 {
82 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
83 dmxDPMSBackend(dmxScreen, level);
84 }
85 #else
86 #define dmxDPMS NULL
87 #endif
88
89 /** Initialize the parts of screen \a idx that require access to the
90 * back-end server. */
91 void
dmxBEScreenInit(ScreenPtr pScreen)92 dmxBEScreenInit(ScreenPtr pScreen)
93 {
94 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
95 XSetWindowAttributes attribs;
96 unsigned long mask;
97 int i, j;
98
99 /* FIXME: The dmxScreenInit() code currently assumes that it will
100 * not be called if the Xdmx server is started with this screen
101 * detached -- i.e., it assumes that dmxScreen->beDisplay is always
102 * valid. This is not necessarily a valid assumption when full
103 * addition/removal of screens is implemented, but when this code is
104 * broken out for screen reattachment, then we will reevaluate this
105 * assumption.
106 */
107
108 pScreen->mmWidth = DisplayWidthMM(dmxScreen->beDisplay,
109 DefaultScreen(dmxScreen->beDisplay));
110 pScreen->mmHeight = DisplayHeightMM(dmxScreen->beDisplay,
111 DefaultScreen(dmxScreen->beDisplay));
112
113 pScreen->whitePixel = dmxScreen->beWhitePixel;
114 pScreen->blackPixel = dmxScreen->beBlackPixel;
115
116 /* Handle screen savers and DPMS on the backend */
117 if (dmxDPMSInit(dmxScreen))
118 pScreen->DPMS = dmxDPMS;
119
120 /* Create root window for screen */
121 mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect;
122 attribs.background_pixel = dmxScreen->beBlackPixel;
123 attribs.event_mask = (KeyPressMask
124 | KeyReleaseMask
125 | ButtonPressMask
126 | ButtonReleaseMask
127 | EnterWindowMask
128 | LeaveWindowMask
129 | PointerMotionMask
130 | KeymapStateMask | FocusChangeMask);
131 attribs.colormap = dmxScreen->beDefColormaps[dmxScreen->beDefVisualIndex];
132 attribs.override_redirect = True;
133
134 dmxScreen->scrnWin =
135 XCreateWindow(dmxScreen->beDisplay,
136 DefaultRootWindow(dmxScreen->beDisplay),
137 dmxScreen->scrnX,
138 dmxScreen->scrnY,
139 dmxScreen->scrnWidth,
140 dmxScreen->scrnHeight,
141 0,
142 pScreen->rootDepth,
143 InputOutput,
144 dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
145 mask, &attribs);
146 dmxPropertyWindow(dmxScreen);
147
148 /*
149 * This turns off the cursor by defining a cursor with no visible
150 * components.
151 */
152 {
153 char noCursorData[] = { 0, 0, 0, 0,
154 0, 0, 0, 0
155 };
156 Pixmap pixmap;
157 XColor color, tmp;
158
159 pixmap = XCreateBitmapFromData(dmxScreen->beDisplay, dmxScreen->scrnWin,
160 noCursorData, 8, 8);
161 XAllocNamedColor(dmxScreen->beDisplay, dmxScreen->beDefColormaps[0],
162 "black", &color, &tmp);
163 dmxScreen->noCursor = XCreatePixmapCursor(dmxScreen->beDisplay,
164 pixmap, pixmap,
165 &color, &color, 0, 0);
166 XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin,
167 dmxScreen->noCursor);
168
169 XFreePixmap(dmxScreen->beDisplay, pixmap);
170 }
171
172 XMapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
173
174 /* Create default drawables (used during GC creation) */
175 for (i = 0; i < dmxScreen->beNumPixmapFormats; i++)
176 for (j = 0; j < dmxScreen->beNumDepths; j++)
177 if ((dmxScreen->bePixmapFormats[i].depth == 1) ||
178 (dmxScreen->bePixmapFormats[i].depth ==
179 dmxScreen->beDepths[j])) {
180 dmxScreen->scrnDefDrawables[i] = (Drawable)
181 XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
182 1, 1,
183 dmxScreen->bePixmapFormats[i].depth);
184 break;
185 }
186 }
187
188 /** Initialize screen number \a pScreen->myNum. */
189 Bool
dmxScreenInit(ScreenPtr pScreen,int argc,char * argv[])190 dmxScreenInit(ScreenPtr pScreen, int argc, char *argv[])
191 {
192 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
193 int i, j;
194
195 if (!dixRegisterPrivateKey(&dmxScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
196 return FALSE;
197 if (!dixRegisterPrivateKey(&dmxColormapPrivateKeyRec, PRIVATE_COLORMAP, 0))
198 return FALSE;
199 if (!dixRegisterPrivateKey(&dmxGlyphSetPrivateKeyRec, PRIVATE_GLYPHSET, 0))
200 return FALSE;
201
202 if (dmxGeneration != serverGeneration) {
203 /* Allocate font private index */
204 dmxFontPrivateIndex = xfont2_allocate_font_private_index();
205 if (dmxFontPrivateIndex == -1)
206 return FALSE;
207
208 dmxGeneration = serverGeneration;
209 }
210
211 if (!dmxInitGC(pScreen))
212 return FALSE;
213 if (!dmxInitWindow(pScreen))
214 return FALSE;
215 if (!dmxInitPixmap(pScreen))
216 return FALSE;
217
218 /*
219 * Initalise the visual types. miSetVisualTypesAndMasks() requires
220 * that all of the types for each depth be collected together. It's
221 * intended for slightly different usage to what we would like here.
222 * Maybe a miAddVisualTypeAndMask() function will be added to make
223 * things easier here.
224 */
225 for (i = 0; i < dmxScreen->beNumDepths; i++) {
226 int depth;
227 int visuals = 0;
228 int bitsPerRgb = 0;
229 int preferredClass = -1;
230 Pixel redMask = 0;
231 Pixel greenMask = 0;
232 Pixel blueMask = 0;
233
234 depth = dmxScreen->beDepths[i];
235 for (j = 0; j < dmxScreen->beNumVisuals; j++) {
236 XVisualInfo *vi;
237
238 vi = &dmxScreen->beVisuals[j];
239 if (vi->depth == depth) {
240 /* Assume the masks are all the same. */
241 visuals |= (1 << vi->class);
242 bitsPerRgb = vi->bits_per_rgb;
243 redMask = vi->red_mask;
244 greenMask = vi->green_mask;
245 blueMask = vi->blue_mask;
246 if (j == dmxScreen->beDefVisualIndex) {
247 preferredClass = vi->class;
248 }
249 }
250 }
251 miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb, preferredClass,
252 redMask, greenMask, blueMask);
253 }
254
255 fbScreenInit(pScreen,
256 NULL,
257 dmxScreen->scrnWidth,
258 dmxScreen->scrnHeight,
259 dmxScreen->beXDPI,
260 dmxScreen->beXDPI, dmxScreen->scrnWidth, dmxScreen->beBPP);
261 (void) dmxPictureInit(pScreen, 0, 0);
262
263 /* Not yet... */
264 pScreen->GetWindowPixmap = NULL;
265 pScreen->SetWindowPixmap = NULL;
266
267 MAXSCREENSALLOC(dmxCursorGeneration);
268 if (dmxCursorGeneration[pScreen->myNum] != serverGeneration) {
269 if (!(miPointerInitialize(pScreen,
270 &dmxPointerSpriteFuncs,
271 &dmxPointerCursorFuncs, FALSE)))
272 return FALSE;
273
274 dmxCursorGeneration[pScreen->myNum] = serverGeneration;
275 }
276
277 DMX_WRAP(CloseScreen, dmxCloseScreen, dmxScreen, pScreen);
278 DMX_WRAP(SaveScreen, dmxSaveScreen, dmxScreen, pScreen);
279
280 dmxBEScreenInit(pScreen);
281
282 /* Wrap GC functions */
283 DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen);
284
285 /* Wrap Window functions */
286 DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen);
287 DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
288 DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen);
289 DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
290 pScreen);
291 DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
292 DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
293 DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
294 DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen);
295 DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
296
297 DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
298 DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
299
300 DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
301
302 /* Wrap Image functions */
303 DMX_WRAP(GetImage, dmxGetImage, dmxScreen, pScreen);
304 DMX_WRAP(GetSpans, dmxGetSpans, dmxScreen, pScreen);
305
306 /* Wrap Pixmap functions */
307 DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen);
308 DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen);
309 DMX_WRAP(BitmapToRegion, dmxBitmapToRegion, dmxScreen, pScreen);
310
311 /* Wrap Font functions */
312 DMX_WRAP(RealizeFont, dmxRealizeFont, dmxScreen, pScreen);
313 DMX_WRAP(UnrealizeFont, dmxUnrealizeFont, dmxScreen, pScreen);
314
315 /* Wrap Colormap functions */
316 DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen);
317 DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen);
318 DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen);
319 DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen);
320
321 /* Wrap Shape functions */
322 DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
323
324 if (!dmxCreateDefColormap(pScreen))
325 return FALSE;
326
327 return TRUE;
328 }
329
330 /** Close the \a pScreen resources on the back-end server. */
331 void
dmxBECloseScreen(ScreenPtr pScreen)332 dmxBECloseScreen(ScreenPtr pScreen)
333 {
334 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
335 int i;
336
337 /* Restore the back-end screen-saver and DPMS state. */
338 dmxDPMSTerm(dmxScreen);
339
340 /* Free the screen resources */
341
342 XFreeCursor(dmxScreen->beDisplay, dmxScreen->noCursor);
343 dmxScreen->noCursor = (Cursor) 0;
344
345 XUnmapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
346 XDestroyWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
347 dmxScreen->scrnWin = (Window) 0;
348
349 /* Free the default drawables */
350 for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
351 if (dmxScreen->scrnDefDrawables[i]) {
352 XFreePixmap(dmxScreen->beDisplay,
353 dmxScreen->scrnDefDrawables[i]);
354 dmxScreen->scrnDefDrawables[i] = (Drawable) 0;
355 }
356 }
357
358 /* Free resources allocated during initialization (in dmxinit.c) */
359 for (i = 0; i < dmxScreen->beNumDefColormaps; i++)
360 XFreeColormap(dmxScreen->beDisplay, dmxScreen->beDefColormaps[i]);
361 free(dmxScreen->beDefColormaps);
362 dmxScreen->beDefColormaps = NULL;
363
364 #if 0
365 /* Do not free visuals, depths and pixmap formats here. Free them
366 * in dmxCloseScreen() instead -- see comment below. */
367 XFree(dmxScreen->beVisuals);
368 dmxScreen->beVisuals = NULL;
369
370 XFree(dmxScreen->beDepths);
371 dmxScreen->beDepths = NULL;
372
373 XFree(dmxScreen->bePixmapFormats);
374 dmxScreen->bePixmapFormats = NULL;
375 #endif
376
377 #ifdef GLXEXT
378 if (dmxScreen->glxVisuals) {
379 XFree(dmxScreen->glxVisuals);
380 dmxScreen->glxVisuals = NULL;
381 dmxScreen->numGlxVisuals = 0;
382 }
383 #endif
384
385 /* Close display */
386 XCloseDisplay(dmxScreen->beDisplay);
387 dmxScreen->beDisplay = NULL;
388 }
389
390 /** Close screen number \a idx. */
391 Bool
dmxCloseScreen(ScreenPtr pScreen)392 dmxCloseScreen(ScreenPtr pScreen)
393 {
394 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
395
396 /* Reset the proc vectors */
397 if (pScreen->myNum == 0) {
398 dmxResetRender();
399 dmxResetFonts();
400 }
401
402 /* Unwrap Shape functions */
403 DMX_UNWRAP(SetShape, dmxScreen, pScreen);
404
405 /* Unwrap the pScreen functions */
406 DMX_UNWRAP(CreateGC, dmxScreen, pScreen);
407
408 DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
409 DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen);
410 DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
411 DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
412 DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
413 DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
414 DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
415 DMX_UNWRAP(WindowExposures, dmxScreen, pScreen);
416 DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
417
418 DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
419 DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
420
421 DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
422
423 DMX_UNWRAP(GetImage, dmxScreen, pScreen);
424 DMX_UNWRAP(GetSpans, dmxScreen, pScreen);
425
426 DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen);
427 DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen);
428 DMX_UNWRAP(BitmapToRegion, dmxScreen, pScreen);
429
430 DMX_UNWRAP(RealizeFont, dmxScreen, pScreen);
431 DMX_UNWRAP(UnrealizeFont, dmxScreen, pScreen);
432
433 DMX_UNWRAP(CreateColormap, dmxScreen, pScreen);
434 DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen);
435 DMX_UNWRAP(InstallColormap, dmxScreen, pScreen);
436 DMX_UNWRAP(StoreColors, dmxScreen, pScreen);
437
438 DMX_UNWRAP(SaveScreen, dmxScreen, pScreen);
439
440 if (dmxScreen->beDisplay) {
441 dmxBECloseScreen(pScreen);
442
443 #if 1
444 /* Free visuals, depths and pixmap formats here so that they
445 * won't be freed when a screen is detached, thereby allowing
446 * the screen to be reattached to be compared to the one
447 * previously removed.
448 */
449 XFree(dmxScreen->beVisuals);
450 dmxScreen->beVisuals = NULL;
451
452 XFree(dmxScreen->beDepths);
453 dmxScreen->beDepths = NULL;
454
455 XFree(dmxScreen->bePixmapFormats);
456 dmxScreen->bePixmapFormats = NULL;
457 #endif
458 }
459
460 DMX_UNWRAP(CloseScreen, dmxScreen, pScreen);
461 return pScreen->CloseScreen(pScreen);
462 }
463
464 static Bool
dmxSaveScreen(ScreenPtr pScreen,int what)465 dmxSaveScreen(ScreenPtr pScreen, int what)
466 {
467 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
468
469 if (dmxScreen->beDisplay) {
470 switch (what) {
471 case SCREEN_SAVER_OFF:
472 case SCREEN_SAVER_FORCER:
473 XResetScreenSaver(dmxScreen->beDisplay);
474 dmxSync(dmxScreen, FALSE);
475 break;
476 case SCREEN_SAVER_ON:
477 case SCREEN_SAVER_CYCLE:
478 XActivateScreenSaver(dmxScreen->beDisplay);
479 dmxSync(dmxScreen, FALSE);
480 break;
481 }
482 }
483
484 return TRUE;
485 }
486